简体   繁体   中英

JSON decoding double nested array in Swift

currently I'm trying to decode JSON with a nested Array. The nested array can have some random numbers of the object inside it. I try to decode it but turns out it return an errors

CodingKeys(stringValue: "itenaries", intValue: nil),
debugDescription : "Expected to decode Array<Any> but found a dictionary 

Sample JSON data

{
   "itenaries": {
      "days":
      [
         [
            {
               "itenary_id":0,
               "itenary_location_name":"Batu Caves Temple"
            }
     
         ],
         [
            {
               "itenary_id":0,
               "itenary_location_name":"KL Tower "
            },
            {
               "itenary_id":1,
               "itenary_location_name":"KL Forest Eco Park"
            }
         ]
      ]
   }
}

My Struct

struct Itenaries : Codable {
    let itenaries : [[Days]]
}

struct Days : Codable {
    let itenary_id : Int
    let itenary_location_name : String
}

Decoding Implementation

let decoder = JSONDecoder()
let itenary = try decoder.decode(Itenaries.self, from: fileData)
print(itenary.itenaries[0][0].itenary_id)

Where do you decode the days key? That's the problem. You need an intermediate struct

struct Root : Decodable {
    let itenaries : Itenary
}

struct Itenary : Decodable {
    let days : [[Days]]
}

...

let result = try decoder.decode(Root.self, from: fileData)
print(result.iternaries.days[0][0].itenary_id)

i'd probably do something like

struct Name:Codable {
    var itenaries:itenaries
}

struct itenaries:Codable {
    var days = [[Days]]
}
struct Days : Codable {
    let itenary_id : Int
    let itenary_location_name : String
}

so basically according the structure of your Json file Root struct -> itenaries -> [[days]]

hope you understand:)

[Edited] you can try these. I'm getting correct result using this approach

Result

struct MainResponse : Codable {
    let itenaries : Itenaries
}

struct Itenaries : Codable {
    let days : [[Days]]
}

struct Days : Codable {
    let itenary_id : Int
    let itenary_location_name : String
}

if let path = Bundle.main.path(forResource: "nested_array", ofType: "json") {
    do {
        let responseData = try Data(contentsOf: URL(fileURLWithPath: path), options: .mappedIfSafe)
        let decoder = JSONDecoder()
        let mainResponse = try decoder.decode(MainResponse.self, from: responseData)
        print(mainResponse.itenaries.days[0][0].itenary_id)
        print(mainResponse.itenaries.days[0][0].itenary_location_name)
        print(mainResponse.itenaries.days[1][0].itenary_id)
        print(mainResponse.itenaries.days[1][0].itenary_location_name)
        print(mainResponse.itenaries.days[1][1].itenary_id)
        print(mainResponse.itenaries.days[1][1].itenary_location_name)

        // output
        // 0
        // Batu Caves Temple
        // 0
        // KL Tower 
        // 1
        // KL Forest Eco Park
    } catch let error {
        print(error.localizedDescription)
    }
}

Your model is not correct, replace it by the following:

struct ItenariesResponse: Codable {
    let itenaries: Itenaries
}

struct Itenaries: Codable {
    let days: [[Day]]
}

struct Day: Codable {
    let itenaryID: Int
    let itenaryLocationName: String

    enum CodingKeys: String, CodingKey {
        case itenaryID = "itenary_id"
        case itenaryLocationName = "itenary_location_name"
    }
}

Then replace the type you decode like that:

let itenary = try decoder.decode(ItenariesResponse.self, from: fileData)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM