0

I am trying to convert the following JSON from the Met Office to a object in Swift 4 but am running in to errors. My plan is to then store in Core Data once the JSON has been decoded. Here is some of the JSON that is returned

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)!

I have created a structure that will be used to convert the data into:

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

I then do the conversion using JSONDecoder:

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

I am getting a keyNotFound error with No value associated with key locations (\"locations\")." I am confused as i'm not sure what value should be accosted with locations as it is just location

Thank you

  • Unrelated to the question at hand, the structure of the JSON doesn't make sense. Notably, it seems strange that the object associated with the key called `Location` is not a single location, but an array of them. Frankly, it feels like that entire layer of the structure isn't adding value. I'd also personally change those numeric fields to return the values without the quotes, so you can parse them as numbers rather than strings. – Rob Mar 07 '18 at 18:42

1 Answers1

0

There are a lots of ways of doing this. But the simplest is probably to create structures to represent each level of your 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)
}
Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • Thanks, this seams to work however just returns nil for all the fields. – William Duckworth Mar 07 '18 at 18:57
  • They can't be `nil`; they're not optionals. I tested this with the JSON in your question and it worked fine. There must be something else going on. – Rob Mar 08 '18 at 16:21