[Help] How to prase this json with dynamic keys

http://test.oye.direct/players.json

How to parse this json. i also need keys.

You'll likely need to parse the top-level structure as a Dictionary and then transform the data into your preferred format.

Maybe something like:

struct Player: Codable {
  var name: String
  var captain: Bool
}

// Top-level of the JSON payload is a dictionary from Country Name to Players
let rawTeams = try decoder.decode([String: [Player]].self, from: data)

Then you can iterate over the keys and values to construct a real Team for each pair of (key, value):

struct Team {
  var country: String
  var players: [Player]
}

let teams = rawTeams.map { (country, players) in
  Team(country: country, players: players)
} 
2 Likes

The approach described by @harlanhaskins is almost certainly best/simplest for your particular situation, but in case you want an alternate approach you could also use a custom coding keys struct that can be initialized with any key string:

struct TeamList: Codable {
    var teams: [Team]

    struct CodingKeys: CodingKey, Hashable {
        var stringValue: String
        
        init(stringValue: String) {
            self.stringValue = stringValue
        }
        
        var intValue: Int? {
            return nil
        }
        
        init?(intValue: Int) {
            return nil
        }
    }
}

Then implement a custom decoder:

struct TeamList: Codable {
    /// ... previous code from above ...
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        let countries = container.allKeys
        var teams: [Team] = []
        for country in countries {
            let team = Team(country: country.stringValue, players: try container.decode([Player].self, forKey: country))
            teams.append(team)
        }
        self.teams = team
    }
}
2 Likes

Thanks @harlanhaskins and @jack for your reply.

But both solutions didn't worked for me.

You never specified the format that you want to decode the data into. What do you want the structure of your model object to look like?

If you want to parse a json object with "dynamic" keys, then you use a dictionary, just like @harlanhaskins did.

Furthermore, "But both solutions didn't worked for me" isn't very helpful You need to actually describe the error that you received.

The following decodes the JSON into a dictionary:

import Foundation

struct Player: Codable {
    let name: String
    let captain: Bool?  // this is missing for some of the items
}

let object = try JSONDecoder().decode(
    [String: [Player]].self, from: jsonData
)

dump(object)

Can’t you give it a default value to assume false if it is missing instead of making it an Optional<Bool>?

You could, but I was decoding it into the exact format that the original JSON is in because @rajesh_raj didn't specify what format he wanted the data decoded into.