Swift 4 декодируемый вложенный JSON со случайными ключевыми атрибутами
У меня проблемы с декодированием 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", чтобы swift распознал случайную переменную, которая содержит мою структуру Dog?
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"
}
}
Стоит помнить, что CodingKey
протокол, не обязательно enum
. Так что вы можете просто сделать этоstruct
и он примет любое случайное строковое значение, которое вы ему укажете.