Декодирование JSON в Swift 4

Я пытаюсь преобразовать следующий JSON из Met Office в объект в Swift 4, но сталкиваюсь с ошибками. Мой план состоит в том, чтобы затем сохранить в Core Data после декодирования JSON. Вот часть JSON, который возвращается

let json = """
{
    "Locations":
        {
            "Location":
                [
                    {
                        "elevation": "50.0",
                        "id": "14",
                        "latitude": "54.9375",
                        "longitude": "-2.8092",
                        "name": "Carlisle Airport",
                        "region": "nw",
                        "unitaryAuthArea": "Cumbria"
                    },
                    {
                        "elevation": "22.0",
                        "id": "26",
                        "latitude": "53.3336",
                        "longitude": "-2.85",
                        "name": "Liverpool John Lennon Airport",
                        "region": "nw",
                        "unitaryAuthArea": "Merseyside"
                    }
                ]
        }
}
""".data(using: .utf8)!

Я создал структуру, которая будет использоваться для преобразования данных в:

struct locations: Decodable {
    var Locations: [location]
    struct location: Decodable {
        var Location: [MetOfficeLocation]
        struct MetOfficeLocation: Decodable {
            var elevation: String
            var id: String
            var latitude: String
            var longitude: String
            var obsSource: String?
            var name: String
            var region: String
            var area: String

            private enum CodingKeys: String, CodingKey {
                case elevation
                case id
                case latitude
                case longitude
                case obsSource
                case name
                case region
                case area = "unitaryAuthArea"
            }
        }
    }
}

Затем я выполняю преобразование с помощью JSONDecoder:

let place = try JSONDecoder().decode([Location].self, from: json)
for i in place {
    print(i.Location[0].name)
}

Я получаю сообщение об ошибке keyNotFound с отсутствием значения, связанного с ключевыми местоположениями («местоположениями»)».

Спасибо


person William Duckworth    schedule 07.03.2018    source источник
comment
Независимо от рассматриваемого вопроса, структура JSON не имеет смысла. В частности, кажется странным, что объект, связанный с ключом с именем Location, представляет собой не одно местоположение, а их массив. Честно говоря, кажется, что весь этот слой структуры не добавляет ценности. Я бы также лично изменил эти числовые поля, чтобы они возвращали значения без кавычек, чтобы вы могли анализировать их как числа, а не строки.   -  person Rob    schedule 07.03.2018


Ответы (1)


Есть много способов сделать это. Но проще всего, вероятно, создать структуры для представления каждого уровня вашего JSON:

struct Location: Codable {
    let elevation: String
    let id: String
    let latitude: String
    let longitude: String
    let name: String
    let region: String
    let area: String
    private enum CodingKeys: String, CodingKey {
        case elevation, id, latitude, longitude, name, region
        case area = "unitaryAuthArea"
    }
}

struct Locations: Codable {
    let locations: [Location]
    enum CodingKeys: String, CodingKey {
        case locations = "Location"
    }
}

struct ResponseObject: Codable {
    let locations: Locations
    enum CodingKeys: String, CodingKey {
        case locations = "Locations"
    }
}

do {
    let responseObject = try JSONDecoder().decode(ResponseObject.self, from: data)
    print(responseObject.locations.locations)
} catch {
    print(error)
}
person Rob    schedule 07.03.2018
comment
Спасибо, этот шов работает, но просто возвращает ноль для всех полей. - person William Duckworth; 07.03.2018
comment
Они не могут быть nil; они не опциональны. Я проверил это с помощью JSON в вашем вопросе, и он работал нормально. Должно быть что-то еще. - person Rob; 08.03.2018