2

I'm pretty green when it comes to working with data flow but I'm trying to force myself through the exercise of building an application to learn it. I'm struggling with how to write my model to correctly reference nested keys in a JSON file.

The JSON looks like this:

[{
    "id": 1001,
    "first_name": "Jimmy",
    "last_name": "Simms",
    "cities": [{
            "name": "New York City",
            "towns": [{
                    "name": "Brooklyn"
                },
                {
                    "name": "Manhatten"
                }
            ]
        },
        {
            "name": "Tokyo",
            "towns": [{
                    "name": "Churo"
                },
                {
                    "name": "Riponggi"
                }
            ]
        }
    ]
}]

What I'm unsure how to do is write a model that lets me target nested elements inside the arrays. Broadly speaking, I'm wondering how you might right a SwiftUI model for this JSON set.

This was kind of my stab in the dark at it:

import SwiftUI

struct MyDataModel: Identifiable {
    var id: Int
    var first_name: String
    var last_name: String
    var cities: Array<Any>
    var cities.name: String
    var cities.towns: Array<Any>
    var cities.towns.name: String
}

But my syntax for accessing the nested arrays "Cities" and then the second level "Towns" is just made up and I can find a reference for how to access nested key's like this? Any help would be much appreciated.

1 Answer 1

2

Basically you want to create structs for the nested components. The MyDataModel has and array of cities, so that requires an array of City objects. Similarly each City has an array of towns so that requires an array of Town objects.

Assuming that you are accessing the JSON from an api and wanting to convert it into objects, you would need to make it conform to Codable, which is fairly straight forward to do. By convention Swift doesn't use snake_case for variable names, instead it uses camel case, so you can use an enum for the coding keys or you can pass an option in the decoder.

struct MyDataModel: Codable, Identifiable {
    let id: Int
    let firstName: String
    let lastName: String
    let cities: [City]

    enum CodingKeys: String, CodingKey {
        case id
        case firstName = "first_name"
        case lastName = "last_name"
        case cities
    }
}

struct City: Codable {
    let name: String
    let towns: [Town]
}

struct Town: Codable {
    let name: String
}

Update

You could do something like this with it, where myDataModels is an array of your MyDataModel:

var body: some View {
    List {
        ForEach(myDataModels) { model in
            Section(header: Text("\(model.firstName) \(model.lastName)")) {
                ForEach(model.cities, id: \.name) { (city: City) in
                    Section(header: Text(city.name).fontWeight(.bold)) {
                        ForEach(city.towns, id: \.name) { town in
                            Text(town.name)
                        }
                    }
                }
            }
        }
    }
}

Which would look like this:

image of possible layout

Sign up to request clarification or add additional context in comments.

5 Comments

Amazing. Thanks Andrew — supremely helpful! Could you share an example of how you might reference the name the town in the view?
@FuegoDeBassi I've added a small code example showing how you could construct a view from the data.
Wow this is exactly what I'm trying to drive toward. I added var myDataModels: [MyDataModel] just above the body call there, but I'm not clear on how to reference it in my PreviewProvider to then reference myDataModels?
I am glad that it has helped. It does sounds like you need further help. I would suggest writing up the relevant parts into a new question (maybe even several questions) so that you can clearly express everything that you need to do, as the comments on SO do not really allow a detailed discussion to take place. For one, code does not format nicely here; and secondly, you are limited to 600 characters, so it makes it hard to express oneself fully.
Point well taken. Writing out exactly what I was trying to express is a helpful exercise in it's own right. stackoverflow.com/questions/58597549/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.