Having issues with SwiftUI ForEach usage

The code below is a json parser example. I used the quick type website to build my structs for reading in the json. All that code works but I am having an issue with looping thru the data read. I am trying to read this is a view, so I can not use a for statement. I am having issues learning how to use the ForEach Statement to loop on the contacts in this json data and print the firstName, lastName for each contact.

This is the Code

let data1JSON = """
[
    {
        "data": {
            "viewer": {
                "__typename": "Member",
                "id": 123,
                "firstName": "d",
                "lastName": "a",
                "emailAddress": "w"
            },
            "league": {
                "id": 1111,
                "name": "a",
                "slug": "b",
                "isMine": true,
                "logo": "g",
                "homePageUrl": "bA",
                "facebookUrl": "www.facebook.com/B",
                "phone": "1",
                "contacts": [
                    {
                        "id": 12,
                        "firstName": "",
                        "lastName": "d",
                        "phone": null,
                        "__typename": "Contact"
                    },
                    {
                        "id": 10,
                        "firstName": "",
                        "lastName": "c",
                        "phone": null,
                        "__typename": "Contact"
                    }
                ],
                "__typename": "League"
            }
        }
    }
]
"""

// MARK: - ApaResultElement
struct ApaResultElement: Codable {
    let data: DataClass
}

// MARK: - DataClass
struct DataClass: Codable {
    let viewer: Viewer
    let league: League
}

// MARK: - League
struct League: Codable {
    let id: Int
    let name, slug: String
    let isMine: Bool
    let logo: String
    let homePageURL, facebookURL, phone: String
    let contacts: [Viewer]
    let typename: String

    enum CodingKeys: String, CodingKey {
        case id, name, slug, isMine, logo
        case homePageURL = "homePageUrl"
        case facebookURL = "facebookUrl"
        case phone, contacts
        case typename = "__typename"
    }
}

// MARK: - Viewer
struct Viewer: Codable {
    let id: Int
    let firstName, lastName: String
    let phone: JSONNull?
    let typename: String
    let emailAddress: String?

    enum CodingKeys: String, CodingKey {
        case id, firstName, lastName, phone
        case typename = "__typename"
        case emailAddress
    }
}

typealias ApaResult = [ApaResultElement]

// MARK: - Encode/decode helpers

class JSONNull: Codable, Hashable {

    public static func == (lhs: JSONNull, rhs: JSONNull) -> Bool {
        return true
    }

    public var hashValue: Int {
        return 0
    }

    public init() {}

    public required init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        if !container.decodeNil() {
            throw DecodingError.typeMismatch(JSONNull.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for JSONNull"))
        }
    }

    public func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        try container.encodeNil()
    }
}


let decoder = JSONDecoder()
let leagueView =  data1JSON.data(using: .utf8)!

do { 
    try decoder.decode([ApaResultElement].self, from: leagueView)
    print("success")
}
catch {
    print("Error found => \(error)")
}



let d1 =  try decoder.decode([ApaResultElement].self, from: leagueView)


// This is where I need help to loop the json to extract all the data
//  I see that I need to loop on each array stuct to do that.

I have looked for a good tutorial on ForEach, but none of the sites I found help me look on this JSON Data.
I am new to swift and the autocomplete feature, so any tips using Apple Developer Documentation or the Code Complete would also be appreciated.

Thanks

Answered by Claude31 in 775389022

I'm not sure I understand your problem, but let's try.

You have an array:

let d1 =  try decoder.decode([ApaResultElement].self, from: leagueView)

Do you get a valid result (what about print it ?).

I assume it's correct.

Then you can loop:

for element in d1 {. // This is an ApaResultElement
  let elementData = element.data // This is a DataClass
  let viewer = elementData.viewer
  let league = elementData.league
  // Continue to extract what you need.
}
Accepted Answer

I'm not sure I understand your problem, but let's try.

You have an array:

let d1 =  try decoder.decode([ApaResultElement].self, from: leagueView)

Do you get a valid result (what about print it ?).

I assume it's correct.

Then you can loop:

for element in d1 {. // This is an ApaResultElement
  let elementData = element.data // This is a DataClass
  let viewer = elementData.viewer
  let league = elementData.league
  // Continue to extract what you need.
}

I modified two structs to be Identifiable. I am testing this code in playground, but want this code in an SwiftUI App ...

// MARK: - ApaResultElement
struct ApaResultElement: Codable, Identifiable {
    var id: UUID = UUID()
    let data: DataClass
}

// MARK: - DataClass
struct DataClass: Codable, Identifiable {
    var id: UUID = UUID()
    let viewer: Viewer
    let league: League

Added this ForEach which compliles but throws exception

let d1 =  try decoder.decode([ApaResultElement].self, from: leagueView). // No Error...


ForEach(d1, id: \.id) { schema in

    Text("\(schema.data.viewer.firstName)")
}

Error found => keyNotFound(CodingKeys(stringValue: "id", intValue: nil), Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "Index 0", intValue: 0)], debugDescription: "No value associated with key CodingKeys(stringValue: "id", intValue: nil) ("id").", underlyingError: nil)) Playground execution terminated: An error was thrown and was not caught: ▿ DecodingError ▿ keyNotFound : 2 elements - .0 : CodingKeys(stringValue: "id", intValue: nil) ▿ .1 : Context ▿ codingPath : 1 element ▿ 0 : _JSONKey(stringValue: "Index 0", intValue: 0) ▿ rep : Rep - index : 0 - debugDescription : "No value associated with key CodingKeys(stringValue: "id", intValue: nil) ("id")." - underlyingError : nil

Having issues with SwiftUI ForEach usage
 
 
Q