Swift, Как разобрать / декодировать JSON, используя Decodable и Codable, Когда ключ неизвестен / динамический - PullRequest
0 голосов
/ 27 сентября 2018

Ниже указан мой JSON, и я не могу декодировать (используя CodingKeys). Данные в ключе регионов представляют собой словарь ("IN-WB", "IN-DL" и т. Д.)....), поскольку ключи являются динамическими, их можно изменить более или менее.

Пожалуйста, помогите мне разобрать то же самое, используя Decodable и Codable.

Все данные должны бытьв пределах одной модели.

{
            "provider_code": "AIIN",
            "name": "Jio India",
            "regions": [
                {
                    "IN-WB": "West Bengal"
                },
                {
                    "IN-DL": "Delhi NCR"
                },
                {
                    "IN-TN": "Tamil Nadu"
                },
                {
                    "IN": "India"
                }
            ]
        }

Ответы [ 2 ]

0 голосов
/ 27 сентября 2018

Один из возможных подходов, без использования словаря.Но все же сначала мы должны найти ключ)

Мне нравится этот стиль, так как мы можем использовать Регионы с самого начала.

// example data.
let string = "{\"provider_code\":\"AIIN\",\"name\":\"Jio India\",\"regions\":[{\"IN-WB\":\"West Bengal\"},{\"IN-DL\":\"Delhi NCR\"},{\"IN-TN\":\"Tamil Nadu\"},{\"IN\":\"India\"}]}"
let data   = string.data(using: .utf8)!

// little helper
struct DynamicGlobalKey: CodingKey {
    var stringValue: String
    init?(stringValue: String) {
        self.stringValue = stringValue
    }

    var intValue: Int? { return nil }
    init?(intValue: Int) { return nil }
}

// model
struct Location: Decodable {
    let providerCode: String
    let name: String
    let regions: [Region]
}

extension Location {
    struct Region: Decodable {
        let key:  String
        let name: String

        init(from decoder: Decoder) throws {
            let container = try decoder.container(keyedBy: DynamicGlobalKey.self)
            key  = container.allKeys.first!.stringValue
            name = try container.decode(String.self, forKey: container.allKeys.first!)
        }
    }
}

// example of decoding.
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase

let location = try decoder.decode(Location.self, from: data)
0 голосов
/ 27 сентября 2018

Просто используйте словарь для регионов.

struct Locations: Codable {
    let providerCode: String
    let name: String
    let regions: [[String: String]]

    enum CodingKeys: String, CodingKey {
        case providerCode = "provider_code"
        case name, regions
    }
}

Невозможно создать конкретную модель для регионов, поскольку вы не знаете имен свойств

...