Как я могу смоделировать Struct из JSON, где некоторые свойства высокого уровня не имеют ключей - PullRequest
0 голосов
/ 20 января 2019

Я пытаюсь создать структуру для моделирования следующего бита JSON, в котором свойства высокого уровня («Синяя команда» и «Зеленая команда») не имеют указанных ключей.

{
  "Teams": [
    {
      "Blue Team": {
        "motto": "We're the best",
        "players": [
          {
            "name": "Bob",
            "skill": "jumping really high",
            "birthday": 1546326611,
          },
          {
            "name": "Julie",
            "skill": "really strong",
            "birthday": 1546413133,
          },
          {
            "name": "Kirsten",
            "skill": "smarty pants",
            "birthday": 1546499716,
          }
        ]
      },
      "Green Team": {... // same structure as above }
    }
  ]
}

Я считаю, что я близко, но я не уверен, как изобразить Blue Team и Red Team. Это то, что я до сих пор:

struct AllTeams: Codable {
    let Teams: [String : Team]

    struct Team: Codable {
        //let <property>: ???
    }

    struct ???: Codable {
        let motto: String
        let players: [Player]
    }

    struct Player: Codable {
        let name: String
        let skill: String
        let birthday: Int // will need to convert this
    }
}

Ответы [ 3 ]

0 голосов
/ 20 января 2019

Полагаю, вы хотите [String: Team] в вашей AllTeams структуре?

Вы можете сделать это:

struct AllTeams: Decodable {
    let teams: [String: Team]

    enum CodingKeys: String, CodingKey {
        case teams = "Teams"
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        teams = (try container.decode([[String: Team]].self, forKey: .teams))[0]
    }
}

struct Team: Codable {
    let motto: String
    let players: [Player]
}

struct Player: Codable {
    let name, skill: String
    let birthday: Date
}

Декодирование:

let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .secondsSince1970
let teams = try! decoder.decode(AllTeams.self, from: json)
print(teams.teams["Blue Team"].motto)
0 голосов
/ 20 января 2019

Вы действительно довольно близки.

Поскольку вы хотите расшифровать команды как словарь, измените структуры на

struct AllTeams: Codable {
    let Teams: [[String : Team]]

    struct Team: Codable {
        let motto: String
        let players: [Player]
    }

    struct Player: Codable {
        let name: String
        let skill: String
        let birthday: Date
    }
}

и декодируйте

 let decoder = JSONDecoder()
 decoder.dateDecodingStrategy = .secondsSince1970
 let result = try decoder.decode(AllTeams.self, from: data)

День рожденияцелое число декодируется как Date

Для более сложного решения по включению командных ключей в структуру Team с пользовательскими CodingKeys взгляните на этот ответ

Примечание:

Рекомендуется соблюдать соглашение об именах и добавлять CodingKeys для сопоставления ключей в верхнем регистре с элементами в нижнем регистре членами структуры

0 голосов
/ 20 января 2019

Исправить JSON (поскольку ваш JSON не полностью и содержит неправильные , ключи в конце дня рождения)

{
    "Teams": [{
        "Blue Team": {
            "motto": "We're the best",
            "players": [{
                    "name": "Bob",
                    "skill": "jumping really high",
                    "birthday": 1546326611
                },
                {
                    "name": "Julie",
                    "skill": "really strong",
                    "birthday": 1546413133
                },
                {
                    "name": "Kirsten",
                    "skill": "smarty pants",
                    "birthday": 1546499716
                }
            ]
        },
        "Green Team": {
            "motto": "We're the best",
            "players": [{
                    "name": "Bob",
                    "skill": "jumping really high",
                    "birthday": 1546326611
                },
                {
                    "name": "Julie",
                    "skill": "really strong",
                    "birthday": 1546413133
                },
                {
                    "name": "Kirsten",
                    "skill": "smarty pants",
                    "birthday": 1546499716
                }
            ]
        }
    }]
}

для 2 клавиш

struct Root: Codable {
    let teams: [Team]

    enum CodingKeys: String, CodingKey {
        case teams = "Teams"
    }
}

struct Team: Codable {
    let blueTeam, greenTeam: BlueTeamClass

    enum CodingKeys: String, CodingKey {
        case blueTeam = "Blue Team"
        case greenTeam = "Green Team"
    }
}

struct BlueTeamClass: Codable {
    let motto: String
    let players: [Player]
}

struct Player: Codable {
    let name, skill: String
    let birthday: Int
}

для динамических клавиш

struct Root: Codable {
    let teams: [[String:Item]]

    enum CodingKeys: String, CodingKey {
        case teams = "Teams"
    }
}

struct Item: Codable {
    let motto: String
    let players: [Player]
}

struct Player: Codable {
    let name, skill: String
    let birthday: Int
}

Decode

do {
     let res = try JSONDecoder().decode(Root.self,from:data)
     print(res)
   }
 catch {
    print(error)
}        
...