Todd Page
Todd Page

Reputation: 51

Parsing Nested JSON SWIFT 4

Could anyone tell me what I am doing wrong?

Here is JSON I'm trying to parse:

{
"results": {
    "AF": {
        "alpha3": "AFG",
        "currencyId": "AFN",
        "currencyName": "Afghan afghani",
        "currencySymbol": "؋",
        "id": "AF",
        "name": "Afghanistan"
    },
    "AI": {
        "alpha3": "AIA",
        "currencyId": "XCD",
        "currencyName": "East Caribbean dollar",
        "currencySymbol": "$",
        "id": "AI",
        "name": "Anguilla"
    }
}

}

My code :

class Results: Codable {
  let results: [Country]

  init(results: [Country]) {
    self.results = results
  }
}

class Country: Codable {

  let currencyId: String
  let currencyName: String
  let currencySymbol: String
  let id: String
  let name: String


  init(currencyId :String, currencyName: String, currencySymbol: String, id: String, name: String ) {

    self.currencyId = currencyId
    self.currencyName = currencyName
    self.currencySymbol = currencySymbol
    self.id = id
    self.name = name

  }
}

I have looked at Apple's Documentation on decoding nested structs, but I still do not understand how to do the different levels of the JSON properly.

Thanks.

Upvotes: 0

Views: 711

Answers (1)

OOPer
OOPer

Reputation: 47876

Check the outlined value for the key "results".

"results": {
    ...
}

{...} represents JSON object. A Swift struct (or class if you think it's better) would be appropriate for JSON object in some cases.

In other cases, Swift Dictionary may be more appropriate.

And each value of this JSON object takes this form:

{
    "alpha3": ...,
    "currencyId": ...,
    "currencyName": ...,
    "currencySymbol": ...,
    "id": ...,
    "name": ...
}

which matches your Country.

So, you just need to change the type of results in your Results class.

class Results: Codable {
    let results: [String: Country]

    init(results: [String: Country]) {
        self.results = results
    }
}

Having the same name (without case) for a property and its class might cause some confusion in the future, but I keep it as is as for now.

You can test it like this:

(Assuming to be tested in the Playground with modified Results and your Country.)

let jsonText = """
{
    "results": {
        "AF": {
            "alpha3": "AFG",
            "currencyId": "AFN",
            "currencyName": "Afghan afghani",
            "currencySymbol": "؋",
            "id": "AF",
            "name": "Afghanistan"
        },
        "AI": {
            "alpha3": "AIA",
            "currencyId": "XCD",
            "currencyName": "East Caribbean dollar",
            "currencySymbol": "$",
            "id": "AI",
            "name": "Anguilla"
        }
    }
}
"""
let jsonData = jsonText.data(using: .utf8)!

let decoder = JSONDecoder()
do {
    let results = try decoder.decode(Results.self, from: jsonData)
    print(results) //-> __lldb_expr_1.Results
} catch {
    print(error)
}

Upvotes: 1

Related Questions