How do you make data in an array nested within JSON data identifiable so you can list the data?

57 views Asked by At

My goal is to display some data from a JSON file in a List in SwiftUI. This is for iOS 17. I have tried a lot of different things and have done some research, but cannot find the solution.

Here's an example of the JSON data:

{
  “key1” : 123,
  “key2” : “word”,
  “key3” : [ 
      {
      “combination” : 193804,
      “color” : “blue”,
      “size” : 2
      },
      {
      “combination” : 785435,
      “color” : “red”,
      “size” : 6
      }, 
      {
      “combination” : 503953,
      “color” : “yellow”,
      “size” : 6
      } ],
   “key4” : “something”
   “key5” : {
    “key4a” : 54
    “key4b” : “thisword”
    “key4c” : “letters”
    }
}

Here are my data models:

struct ThisData: Decodable {
    let key1: Int
    let key2: String
    let key3: [OtherData]
    let key4: String
    let key5: ThatData

    struct OtherData: Decodable {
        let combination: Int
        let color: String
        let size: Int
    }

    struct ThatData: Decodable {
        let key4a: Int
        let key4b: String
        let key4c: String
    }
}

Here's the view where I'm trying to display the list. What I want to do is display, in three rows, the values for the keys "combination," "color," and "size" that are included in the array under "key3".

import SwiftUI

struct ThisView: View {
    
    @State private var thisData: [ThisData.OtherData] = []
    
    var body: some View {
    
                ScrollView {
                   
                    List(thisData) { info in
                        
                        HStack {
                            
                            Text("\(code to display variable from OtherData struct)")

                        }

                    }

                }

     }

}

At this point, I get the following error for the view:

Initializer 'init(_:rowContent:)' requires that 'CurrentConditions.CurrentData' conform to 'Identifiable'

I understand why -- there needs to be a unique identifier for the data nested under "key3." I did find a suggested solution, but it only works for a key in the "ThisData" struct/data model.

extension CurrentConditions: Identifiable {
    var id: Int { return XXX }
}

Nothing I replace XXX with works. I feel like I'm close, but I just don't have the background knowledge to figure it out. I've spent about four hours on this.

1

There are 1 answers

0
workingdog support Ukraine On BEST ANSWER

First of all, your models should match the json data. The simple way to do that is to copy and paste your json into https://app.quicktype.io/ it will generate most of the code for you.

To rename or omit certain properties from decoding, use CodingKeys, for example:

 struct ThisData: Identifiable, Decodable {
     let id = UUID()  // <--- here
     let key1: Int
     let key2: String
     //...
 
 enum CodingKeys: String, CodingKey { // <--- here, no id present, so will not be decoded
     case key1
     case key2 = "created_at"  // <--- here, the json data field to decode
     // ....
 }

 struct OtherData: Identifiable, Decodable {
     let id = UUID()  // <--- here
     let combination: Int
     let color: String
     let size: Int
 
     enum CodingKeys: String, CodingKey { // <--- here, no id present, so will not be decoded
         case combination, color, size
     }
 }

Similarly for your other models. This is a common approach to make your struct Identifiable and not decode the id.

It is very useful to have your models with a unique id, especially those in arrays, like your OtherData

To display the list in three rows with the data "combination," "color," and "size", use something like this:

 List(thisData) { info in
     VStack {
         Text("\(info.combination)")
         Text(info.color)
         Text("\(info.size)")
     }
 }

Note, no need for ScrollView if you have a List.