具有随机键属性的Swift 4可解码嵌套json

时间:2017-12-02 11:25:39

标签: json swift4 decodable

我在解码json方面遇到了问题。我已经遵循了很多教程,但没有使用复杂的json结构。为简单起见,我最小化了代码并使用Dog作为示例。

在接下来的json中,我大多只对Dog结构感兴趣。 json"数据"属性包含随机狗名称。所以我不能使用编码密钥,因为我不知道属性名称。

{
     "Response": "success"
     "BaseLinkUrl": "https://wwww.example.com",
     "Data": {
         "Max": {
             "name": "Max",
             "breed": "Labrador"
         },
         "Rocky": {
             "name": "Rocky",
             "breed": "Labrador"
         },
         ...
    }
}

我有以下结构:

struct DogResponse : Decodable {
    let data : DogResponseData

    enum CodingKeys: String, CodingKey {
        case data = "Data"
    }
}

struct DogResponseData: Decodable {
    let dog: Dog //this is a random variable name

    enum CodingKeys: String, CodingKey {
        case dog = "??random_variable_dog_name??"
    }
}

struct Dog: Decodable {
    let name: String
    let type: String

    enum CodingKeys: String, CodingKey {
        case name
        case type = "breed"
    }
}

收集狗结构:

let dogResponse = try JSONDecoder().decode(DogResponse.self, from: data)
print(dogResponse)

在我的" DogResponseData"中我需要做什么? struct for swift识别包含我的Dog结构的随机变量?

2 个答案:

答案 0 :(得分:1)

一种可能的解决方案是编写自定义初始值设定项以将字典解码为[String:Dog]并将值映射到数组

struct Dog : Decodable {
    let name : String
    let breed : String
}

struct DogResponse : Decodable {
    let dogs : [Dog]

    private enum CodingKeys: String, CodingKey {
        case data = "Data"
    }

    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        let data = try values.decode([String : Dog].self, forKey: .data)
        dogs = Array(data.values)
    }
}
let dogResponse = try JSONDecoder().decode(DogResponse.self, from: data)
print(dogResponse.dogs)

=============================================== ============================

或者如果你想保持字典结构,它仍然更短

struct Dog : Decodable {
    let name : String
    let breed : String
}

struct DogResponse : Decodable {
    let dogs : [String : Dog]

    private enum CodingKeys: String, CodingKey {
        case dogs = "Data"
    }
}

答案 1 :(得分:1)

请记住,#endif是一个协议,不一定是CodingKey。因此,您可以将其设置为enum,它将接受您向其抛出的任何随机字符串值。