I'm Unable to Parse this JSON,
{
"Teams": {
"4": {
"Name_Full": "India",
"Players": {
"3632": {
"Name_Full": "Dinesh Karthik",
"Batting": {
"Runs": "1738"
},
"Bowling": {
"Wickets": "0"
}
}
}
},
"5": {
"Name_Full": "New Zealand",
"Players": {
"3752": {
"Position": "4",
"Name_Full": "Ross Taylor",
"Batting": {
"Runs": "7890"
},
"Bowling": {
"Wickets": "0"
}
}
}
}
}
}
I have tried creating Model Like this, but I'm getting error for naming "4" and "5"
struct CricketTeam: Codable {
var Teams: Teams
}
struct Teams: Codable {
var teamID: TeamID
}
struct TeamID: Codable {
var teamPlayers: TeamPlayers
}
struct TeamPlayers: Codable {
var Name_Full: String
var playerID: PlayerID
}
struct PlayerID: Codable {
var Name_Full: String
}
Is my Model wrong? I need to show a list contains Players Info, Like Name and Batting and Bowling Skills
Is my Model wrong?
Yes. Starting from the top:
Your top level object is a JSON object with one property called Teams
struct Everything: Decodable
{
var Teams: ...
}
What is the type of that object? Well, it is also a JSON object keyed by a number (written as a string), and "Teams" implies a collection of teams, so we'll go for a Swift dictionary of a new type called Team
struct Everything: Decodable
{
var Teams: [String : Team]
}
So what does a Team
look like? Let's have a look at the JSON we are trying to decode.
{
"Name_Full": "India",
"Players": {
"3632": {
"Name_Full": "Dinesh Karthik",
"Batting": {
"Runs": "1738"
},
"Bowling": {
"Wickets": "0"
}
}
}
}
So a Team has a name and a collection of players. Thus, the team should look something like this.
struct Team: Decodable
{
var Name_Full: String
var Players: [String : Player]
}
We can go through a similar exercise for the Player type. This is the JSON for a player
{
"Position": "4",
"Name_Full": "Ross Taylor",
"Batting": {
"Runs": "7890"
},
"Bowling": {
"Wickets": "0"
}
}
We have two simple properties and two properties that are JSON objects, so we'll create a Player
struct, a Bowling
struct and a Batting
struct. Our final complete model looks like this.
struct Evertything: Decodable
{
var Teams: [String : Team]
}
struct Team: Decodable
{
var Name_Full: String
var Players: [String : Player]
}
struct Player: Decodable
{
var Name_Full : String
var Batting : Batting
var Bowling : Bowling
var Position: String?
}
struct Batting: Decodable
{
var Runs : String
}
struct Bowling: Decodable
{
var Wickets : String
}
This is sufficient to deserialise the JSON from the question. The only issue now is that the ids for a player and a team exist only as dictionary keys. An individual Team
or Player
doesn't know its id. This is a bit tricky because putting the id in the Player
and keeping the collection as a Dictionary
leads us to potential logical inconsistencies. However, we can do it with a custom init(from:)
Here's a way to do it. Each Team
has an id and the dictionary of teams is transformed to an array to avoid the potential logical inconsistency. Since we need coding keys, I have taken the opportunity to create coding keys that translate the JSON keys to Swift conventional property names.
struct Everything: Decodable
{
enum CodingKeys: String, CodingKey
{
case teams = "Teams"
}
init(teams: [Team])
{
self.teams = teams
}
var teams: [Team]
init(from decoder: Decoder) throws
{
let container = try decoder.container(keyedBy: CodingKeys.self)
var teamsDict = try container.decode([String : Team].self, forKey: .teams)
for key in teamsDict.keys
{
teamsDict[key]?.id = key
}
self.init(teams: Array(teamsDict.values))
}
}
struct Team: Decodable
{
enum CodingKeys: String, CodingKey
{
case name = "Name_Full"
case players = "Players"
}
var id: String = ""
var name: String
var players: [String : Player]
}
You should do a similar trick with the Players
property of a Team