Parsing Json Using Swift

Hi. I am having issues with parsing through json data and saving it properly on firestore. For the most part i got it working, but for a certain key, im not able to. My current function looks like this:

func fetchWordInformationFromAPI(word: String, completion: @escaping ([String: Any]?) -> Void) {
        let apiUrl = "https://www.dictionaryapi.com/api/v3/references/collegiate/json/\(word)?key=(hidden this for now)

        if let url = URL(string: apiUrl) {
            let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
                if let error = error {
                    print("Error: \(error)")
                    completion(nil) // Notify the completion closure of the failure
                } else if let data = data {
                    print(String(data: data, encoding: .utf8) ?? "Invalid data")
                    do {
                        if let jsonArray = try JSONSerialization.jsonObject(with: data, options: []) as? [[String: Any]] {
                            // Check if the array is not empty
                            if let firstObject = jsonArray.first {
                                // Create a dictionary to store the word information
                                var wordInformation: [String: Any] = [:]

                                // Extract the desired information for the current word
                                if let meta = firstObject["meta"] as? [String: Any] {
                                    wordInformation["id"] = meta["id"]
                                    wordInformation["section"] = meta["section"]
                                    wordInformation["offensive"] = meta["offensive"]
                                }

                                if let hwi = firstObject["hwi"] as? [String: Any] {
                                    wordInformation["headword"] = hwi["hw"]
                                    // Extract additional fields from the hwi object
                                    if let prsArray = hwi["prs"] as? [[String: Any]] {
                                        var pronunciations: [String] = []
                                        for prs in prsArray {
                                            if let mw = prs["mw"] as? String {
                                                pronunciations.append(mw)
                                            }
                                            if let sound = prs["sound"] as? [String: Any] {
                                                if let audio = sound["audio"] as? String {
                                                    pronunciations.append(audio)
                                                }
                                            }
                                            // Extract any additional fields you need from the prs object
                                        }
                                        wordInformation["pronunciations"] = pronunciations
                                    }
                                }

                                if let fl = firstObject["fl"] as? String {
                                    wordInformation["partOfSpeech"] = fl
                                }

                                if let shortDefArray = firstObject["shortdef"] as? [String] {
                                    if let firstShortDef = shortDefArray.first {
                                        wordInformation["shortDefinition"] = firstShortDef
                                    }
                                }
                                
                                if let etymologyArray = firstObject["et"] as? [[String: Any]] {
                                    var etymologyTexts: [String] = []
                                    for et in etymologyArray {
                                        if let textEntry = et["text"] as? String {
                                            etymologyTexts.append(textEntry)
                                        }
                                    }
                                    if !etymologyTexts.isEmpty {
                                        wordInformation["etymology"] = etymologyTexts.joined(separator: "; ")
                                    } else {
                                        print("No etymology text found in any inner array")
                                    }
                                } else {
                                        
                                }

                                print("etymology is " + (wordInformation["etymology"] as? String ?? ""))

                                completion(wordInformation) // Pass the word information to the completion closure
                                return
                            }
                        }
                    } catch {
                        print("Error parsing JSON: \(error)")
                    }
                }

                completion(nil) // Notify the completion closure of the failure
            }
            task.resume()
        } else {
            completion(nil) // Notify the completion closure of the failure
        }
    }

and the json data i am trying to work with looks like this:

[{"meta":{"id":"corn:1","uuid":"599ab34f-3845-47b7-a405-28baaf8e788f","sort":"035610400","src":"collegiate","section":"alpha","stems":["Indian corn","corn","corns","maize"],"offensive":false},"hom":1,"hwi":{"hw":"corn","prs":[{"mw":"\u02c8k\u022frn","sound":{"audio":"corn0001","ref":"c","stat":"1"}}]},"fl":"noun","lbs":["often attributive"],"def":[{"sseq":[[["sense",{"sn":"1","sls":["chiefly dialectal"],"dt":[["text","{bc}a small hard particle {bc}{sx|grain||}"]]}]],[["sense",{"sn":"2","dt":[["text","{bc}a small hard seed "],["uns",[[["text","usually used in combination "],["vis",[{"t":"pepper{it}corn{\/it}"},{"t":"barley{it}corn{\/it}"}]]]]]]}]],[["sense",{"sn":"3","lbs":["British"],"dt":[["text","{bc}the grain of a cereal grass that is the primary crop of a region (such as wheat in Britain and oats in Scotland and Ireland)"]],"sdsense":{"sd":"also","dt":[["text","{bc}a plant that produces corn"]]}}]],[["sense",{"sn":"4 a","dt":[["text","{bc}a tall annual cereal grass ({it}Zea mays{\/it}) originally domesticated in Mexico and widely grown for its large elongated ears of starchy seeds "],["ca",{"intro":"called also","cats":[{"cat":"Indian corn"},{"cat":"maize"}]}]]}],["sense",{"sn":"b","dt":[["text","{bc}the typically yellow or whitish seeds of corn used especially as food for humans and livestock"]]}],["sense",{"sn":"c","dt":[["text","{bc}an ear of corn with or without its leafy outer covering"]]}]],[["sense",{"sn":"5","dt":[["text","{bc}{sx|corn whiskey||}"]]}]],[["sense",{"sn":"6 a","dt":[["text","{bc}something (such as writing, music, or acting) that is {d_link|corny|corny:1}"]]}],["sense",{"sn":"b","dt":[["text","{bc}the quality or state of being corny {bc}{sx|corniness||}"]]}]],[["sense",{"sn":"7","dt":[["text","{bc}{sx|corn snow||}"]]}]]]}],"et":[["text","Middle English, going back to Old English, \u0022grain of a cereal grass, seed, berry,\u0022 going back to Germanic {it}*kurno-{\/it} (whence also Old Frisian, Old Saxon, Old High German \u0026 Old Norse {it}korn{\/it} \u0022grain of a cereal grass, seed,\u0022 Gothic {it}kaurn{\/it}), going back to European Indo-European {it}*\u01f5r\u0325H-no-,{\/it} whence also Latin {it}gr\u0101num{\/it} \u0022seed, especially of a cereal grass,\u0022 Old Irish {it}gr\u00e1n,{\/it} Welsh {it}grawn,{\/it} Old Church Slavic {it}zr\u012dno{\/it} \u0022grain, seed,\u0022 Serbian \u0026 Croatian {it}z\u0211no,{\/it} Russian {it}zern\u00f3,{\/it} Lithuanian{it} \u017e\u00ecrnis{\/it} \u0022pea\u0022"],["et_snote",[["t","The noun {it}*\u01f5r\u0325H-no{\/it} is sometimes taken to be a zero-grade derivative of Indo-European {it}*\u01f5erh{inf}2{\/inf}-{\/it} \u0022become old, ripen\u0022 (see {et_link|geriatric:1|geriatric:1}), but this has been disputed."]]]],"date":"before 12th century{ds||1||}","shortdef":["a small hard particle : grain","a small hard seed \u2014usually used in combination","the grain of a cereal grass that is the primary crop of a region (such as wheat in Britain and oats in Scotland and Ireland); also : a plant that produces corn"]},{"meta":{"id":"corn:2","uuid":"5f388e20-71b8-47f5-ac65-ee8b69f58114","sort":"035610500","src":"collegiate","section":"alpha","stems":["corn","corned","corning","corns"],"offensive":false},"hom":2,"hwi":{"hw":"corn"},"fl":"verb","ins":[{"if":"corned"},{"if":"corn*ing"},{"if":"corns"}],"def":[{"vd":"transitive verb","sseq":[[["sense",{"sn":"1","dt":[["text","{bc}to form into grains {bc}{sx|granulate||}"]]}]],[["sense",{"sn":"2 a","dt":[["text","{bc}to preserve or season with salt in grains"]]}],["sense",{"sn":"b","dt":[["text","{bc}to cure or preserve in brine containing preservatives and often seasonings "],["vis",[{"t":"{wi}corned{\/wi} beef"}]]]}]],[["sense",{"sn":"3","dt":[["text","{bc}to feed with corn"]]}]]]}],"et":[["text","derivative of {et_link|corn:1|corn:1}"]],"date":"1560{ds||1||}","shortdef":["to form into grains : granulate","to preserve or season with salt in grains","to cure or preserve in brine containing preservatives and often seasonings"]},{"meta":{"id":"corn:3","uuid":"faf448a7-8eba-41d1-8a8f-75f256e88666","sort":"035610600","src":"collegiate","section":"alpha","stems":["Indian corn","corn","corns","maize"],"offensive":false},"hom":3,"hwi":{"hw":"corn"},"fl":"noun","def":[{"sseq":[[["sense",{"dt":[["text","{bc}a local hardening and thickening of epidermis (as on a toe)"]]}]]]}],"et":[["text","Middle English {it}corne,{\/it} probably borrowed from Medieval Latin {it}corn\u016b{\/it} \u0022horn, horny excrescence,\u0022 going back to Latin, \u0022horn\u0022 {ma}{mat|horn|}{\/ma} "],["et_snote",[["t","Late Old English {it}corn{\/it} in this sense, attested in the medical text {it}Lacnunga,{\/it} a collection of remedies, charms and prayers, may be from Latin or an extended sense of Old English {it}corn{\/it} {et_link|corn:1|corn:1}."]]]],"date":"15th century","shortdef":["a local hardening and thickening of epidermis (as on a toe)"]},{"meta":{"id":"corn borer","uuid":"5b2228f6-49cd-4de4-939a-c08f35f9634d","sort":"035610900","src":"collegiate","section":"alpha","stems":["corn borer","corn borers"],"offensive":false},"hwi":{"hw":"corn borer"},"fl":"noun","def":[{"sseq":[[["bs",{"sense":{"dt":[["text","{bc}any of several insects that bore in the stalks or ears of corn: such as"]]}}],["sense",{"sn":"a","dt":[["text","{bc}an Old World moth ({it}Ostrinia nubilalis{\/it}) widespread in eastern and central North America where its larva is a major pest in the stems, crowns, and fruits of crop plants and especially corn "],["ca",{"intro":"called also","cats":[{"cat":"European corn borer"}]}]]}],["sense",{"sn":"b","dt":[["text","{bc}a {d_link|pyralid|pyralid} moth ({it}Diatraea grandiosella{\/it}) whose larva causes serious damage especially to corn crops by boring in the stalks "],["ca",{"intro":"called also","cats":[{"cat":"southwestern corn borer"}]}]]}]]]}],"date":"1853","shortdef":["any of several insects that bore in the stalks or ears of corn: such as","an Old World moth (Ostrinia nubilalis) widespread in eastern and central North America where its larva is a major pest in the stems, crowns, and fruits of crop plants and especially corn \u2014called also European corn borer","a pyralid moth (Diatraea grandiosella) whose larva causes serious damage especially to corn crops by boring in the stalks \u2014called also southwestern corn borer"]},{"meta":{"id":"corn bread","uuid":"6d321387-08e9-47d3-a927-960a16ba1442","sort":"035611000","src":"collegiate","section":"alpha","stems":["corn bread","corn breads"],"offensive":false},"hwi":{"hw":"corn bread"},"fl":"noun","def":[{"sseq":[[["sense",{"dt":[["text","{bc}bread made with cornmeal"]]}]]]}],"date":"1719","shortdef":["bread made with cornmeal"]},{"meta":{"id":"corn chip","uuid":"bf6ae52f-e90c-4ed9-87e4-a82c6406d1c8","sort":"035611100","src":"collegiate","section":"alpha","stems":["corn chip","corn chips"],"offensive":false},"hwi":{"hw":"corn chip"},"fl":"noun","def":[{"sseq":[[["sense",{"dt":[["text","{bc}a piece of a dry crisp snack food prepared from a seasoned cornmeal batter"]]}]]]}],"date":"1932","shortdef":["a piece of a dry crisp snack food prepared from a seasoned cornmeal batter"]},{"meta":{"id":"corn cockle","uuid":"8d418cc5-3cf3-4971-b8f6-4363aa4277ef","sort":"035611400","src":"collegiate","section":"alpha","stems":["corn cockle","corn cockles"],"offensive":false},"hwi":{"hw":"corn cockle"},"fl":"noun","def":[{"sseq":[[["sense",{"dt":[["text","{bc}an annual hairy weed ({it}Agrostemma githago{\/it}) of the pink family with purplish-red flowers that is found in grain fields"]]}]]]}],"date":"1713","shortdef":["an annual hairy weed (Agrostemma githago) of the pink family with purplish-red flowers that is found in grain fields"]},{"meta":{"id":"corn dodger","uuid":"5b26e755-8410-4f35-9141-3cd870909dee","sort":"035611700","src":"collegiate","section":"alpha","stems":["corn dodger","corn dodgers"],"offensive":false},"hwi":{"hw":"corn dodger"},"fl":"noun","def":[{"sls":["chiefly Southern US and Midland US"],"sseq":[[["sense",{"dt":[["text","{bc}a cake of corn bread that is fried, baked, or boiled as a dumpling"]]}]]]}],"date":"1834","shortdef":["a cake of corn bread that is fried, baked, or boiled as a dumpling"]},{"meta":{"id":"corn dog","uuid":"5656148b-ebd9-4dbe-8b93-a2728aa8cc97","sort":"035611800","src":"collegiate","section":"alpha","stems":["corn dog","corn dogs"],"offensive":false},"hwi":{"hw":"corn dog"},"fl":"noun","def":[{"sseq":[[["sense",{"dt":[["text","{bc}a frankfurter dipped in cornmeal batter, fried, and served on a stick"]]}]]]}],"date":"1939","shortdef":["a frankfurter dipped in cornmeal batter, fried, and served on a stick"]},{"meta":{"id":"corn earworm","uuid":"99f08f7f-f2e7-41e3-8d92-b5c4f9901cd8","sort":"035612000","src":"collegiate","section":"alpha","stems":["corn earworm","corn earworms"],"offensive":false},"hwi":{"hw":"corn ear*worm","prs":[{"mw":"-\u02c8ir-\u02ccw\u0259rm","sound":{"audio":"corn_e01","ref":"c","stat":"1"}}]},"fl":"noun","def":[{"sseq":[[["sense",{"dt":[["text","{bc}a noctuid moth ({it}Helicoverpa zea{\/it} synonym {it}Heliothis zea{\/it}) whose large striped yellow-headed larva is especially destructive to corn, tomatoes, tobacco, and cotton bolls"]]}]]]}],"date":"1802","shortdef":["a noctuid moth (Helicoverpa zea synonym Heliothis zea) whose large striped yellow-headed larva is especially destructive to corn, tomatoes, tobacco, and cotton bolls"]}]

i am having an issue where i am trying to save the etymology of the word, but for some reason cant parst it correctly. the specific key i am looking to store is "et"

Any help is appreciated

Have you tried using https://app.quicktype.io to evaluate your json data and generate a decoding data model?

This is the output from that tool using the json you supplied which might give you a clue to solving your issue:

// This file was generated from JSON Schema using quicktype, do not modify it directly.
// To parse the JSON, add this file to your project and do:
//
//   let welcome = try? JSONDecoder().decode(Welcome.self, from: jsonData)

import Foundation

// MARK: - WelcomeElement
struct WelcomeElement: Codable {
    let meta: Meta
    let hom: Int?
    let hwi: Hwi
    let fl: FL
    let lbs: [String]?
    let def: [Def]
    let et: [[Et]]?
    let date: String
    let shortdef: [String]
    let ins: [In]?
}

// MARK: - Def
struct Def: Codable {
    let sseq: [[[SseqElement]]]
    let vd: String?
    let sls: [String]?
}

enum SseqElement: Codable {
    case enumeration(SseqEnum)
    case sseqClass(SseqClass)

    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        if let x = try? container.decode(SseqEnum.self) {
            self = .enumeration(x)
            return
        }
        if let x = try? container.decode(SseqClass.self) {
            self = .sseqClass(x)
            return
        }
        throw DecodingError.typeMismatch(SseqElement.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for SseqElement"))
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        switch self {
        case .enumeration(let x):
            try container.encode(x)
        case .sseqClass(let x):
            try container.encode(x)
        }
    }
}

// MARK: - SseqClass
struct SseqClass: Codable {
    let sn: String?
    let sls: [String]?
    let dt: [[SseqDt]]?
    let lbs: [String]?
    let sdsense: Sdsense?
    let sense: Sense?
}

enum SseqDt: Codable {
    case fluffyDt(FluffyDt)
    case string(String)
    case unionArray([TentacledDt])

    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        if let x = try? container.decode([TentacledDt].self) {
            self = .unionArray(x)
            return
        }
        if let x = try? container.decode(String.self) {
            self = .string(x)
            return
        }
        if let x = try? container.decode(FluffyDt.self) {
            self = .fluffyDt(x)
            return
        }
        throw DecodingError.typeMismatch(SseqDt.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for SseqDt"))
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        switch self {
        case .fluffyDt(let x):
            try container.encode(x)
        case .string(let x):
            try container.encode(x)
        case .unionArray(let x):
            try container.encode(x)
        }
    }
}

enum TentacledDt: Codable {
    case purpleDt(PurpleDt)
    case unionArrayArray([[StickyDt]])

    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        if let x = try? container.decode([[StickyDt]].self) {
            self = .unionArrayArray(x)
            return
        }
        if let x = try? container.decode(PurpleDt.self) {
            self = .purpleDt(x)
            return
        }
        throw DecodingError.typeMismatch(TentacledDt.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for TentacledDt"))
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        switch self {
        case .purpleDt(let x):
            try container.encode(x)
        case .unionArrayArray(let x):
            try container.encode(x)
        }
    }
}

enum StickyDt: Codable {
    case purpleDtArray([PurpleDt])
    case string(String)

    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        if let x = try? container.decode([PurpleDt].self) {
            self = .purpleDtArray(x)
            return
        }
        if let x = try? container.decode(String.self) {
            self = .string(x)
            return
        }
        throw DecodingError.typeMismatch(StickyDt.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for StickyDt"))
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        switch self {
        case .purpleDtArray(let x):
            try container.encode(x)
        case .string(let x):
            try container.encode(x)
        }
    }
}

// MARK: - PurpleDt
struct PurpleDt: Codable {
    let t: String
}

// MARK: - FluffyDt
struct FluffyDt: Codable {
    let intro: String
    let cats: [Cat]
}

// MARK: - Cat
struct Cat: Codable {
    let cat: String
}

// MARK: - Sdsense
struct Sdsense: Codable {
    let sd: String
    let dt: [[String]]
}

// MARK: - Sense
struct Sense: Codable {
    let dt: [[String]]
}

enum SseqEnum: String, Codable {
    case bs = "bs"
    case sense = "sense"
}

enum Et: Codable {
    case string(String)
    case stringArrayArray([[String]])

    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        if let x = try? container.decode([[String]].self) {
            self = .stringArrayArray(x)
            return
        }
        if let x = try? container.decode(String.self) {
            self = .string(x)
            return
        }
        throw DecodingError.typeMismatch(Et.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for Et"))
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        switch self {
        case .string(let x):
            try container.encode(x)
        case .stringArrayArray(let x):
            try container.encode(x)
        }
    }
}

enum FL: String, Codable {
    case noun = "noun"
    case verb = "verb"
}

// MARK: - Hwi
struct Hwi: Codable {
    let hw: String
    let prs: [PR]?
}

// MARK: - PR
struct PR: Codable {
    let mw: String
    let sound: Sound
}

// MARK: - Sound
struct Sound: Codable {
    let audio, ref, stat: String
}

// MARK: - In
struct In: Codable {
    let inIf: String

    enum CodingKeys: String, CodingKey {
        case inIf = "if"
    }
}

// MARK: - Meta
struct Meta: Codable {
    let id, uuid, sort: String
    let src: Src
    let section: Section
    let stems: [String]
    let offensive: Bool
}

enum Section: String, Codable {
    case alpha = "alpha"
}

enum Src: String, Codable {
    case collegiate = "collegiate"
}

typealias Welcome = [WelcomeElement]