我如何从 JSON 建模一个结构,其中一些高级属性没有键

How can I model a Struct from JSON where some high level properties don't have keys

我正在尝试创建一个结构来模拟 JSON 的以下位,其中高级属性("Blue Team" 和 "Green Team")没有指定的键。

{
  "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 TeamRed 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
    }
}

更正 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
}

解码

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

我想你想要 [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)

你真的很接近

因为你想将团队解码为字典,将结构更改为

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

有关使用自定义 CodingKey 将团队密钥包含在 Team 结构中的更复杂的解决方案,请查看

注:

我们鼓励您遵守命名约定并添加 CodingKeys 以将 大写 键映射到 小写 结构成员