Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

decoding a nested array in swift 4 [duplicate]

Tags:

swift

swift4

take the following JSON:

let rawJson =
"""
[
      {
          "id": 1,
          "name":"John Doe"
      },
      {
          "id": 2,
          "name":"Luke Smith"
      },
 ]
"""

and User model:

struct User: Decodable {
    var id: Int
    var name: String
}

It's pretty simple to decode, like so:

let data = rawJson.data(using: .utf8)
let decoder = JSONDecoder()
let users = try! decoder.decode([User].self, from: data!)

But what if the JSON looks like this, where the top level is a dictionary and need to fetch the array of users:

let json =
"""
{
    "users":
    [
        {
          "id": 1,
          "name":"John Doe"
        },
        {
          "id": 2,
          "name":"Luke Smith"
        },
    ]
}
"""

What's the most effective solution to reading the JSON? I could definitely create another struct like this:

struct SomeStruct: Decodable {
    var posts: [Post]
}

and decode like so:

let users = try! decoder.decode(SomeStruct.self, from: data!)

but it doesn't feel right doing it that way, creating a new model object just because the array is nested inside a dictionary.

like image 853
luke Avatar asked Oct 10 '17 15:10

luke


1 Answers

If you want to take advantage of JSONDecoder you have to create a nested struct(ure).

I recommend to use the name Root for the root object and put the child struct into Root

struct Root : Decodable {

    struct User : Decodable {
        let id: Int
        let name: String
    }

    let users : [User]
}

let json = """
{
    "users": [{"id": 1, "name":"John Doe"},
              {"id": 2, "name":"Luke Smith"}]
}
"""

let data = Data(json.utf8)
do {
    let root = try JSONDecoder().decode(Root.self, from: data)
    print(root.users)
} catch {
    print(error)
}
like image 53
vadian Avatar answered Sep 21 '22 08:09

vadian