Teddy Higgins
Teddy Higgins

Reputation: 140

How to parse json in swift 4 an array inside an array

I'm having trouble accessing the StatusList array from this API response. How would I get that information?

my current code is and does not work.

let parsedData = try JSONSerialization.jsonObject(with: data!) as! [String:Any]

for list in (parsedData["StatusList"] as? [String])!{
    for shipmentstatus in list["Details"]{
                        //doesn't work
                    }
                }

here is the JSON

{
   "MobileAPIError":"",
   "StatusList":{
      "ErrorMessage":"",
      "Details":[
     {
        "Pro":"000000000",
        "BlNumber":"000000",
        "ReferenceNumber":"",
        "Scac":"CNWY",
        "Carrier":"XPO LOGISTICS FREIGHT, INC.",
        "ShipperCode":"xx999",
        "ShipperName":"W B EQUIPMENT",
        "ShipperCity":"WOOD RIDGE",
        "ShipperState":"NJ"
     },
     {
        "Pro":"0000000",
        "BlNumber":"#00000-R",
        "ReferenceNumber":"",
        "Scac":"CNWY",
        "Carrier":"XPO LOGISTICS FREIGHT, INC.",
        "ShipperCode":"xx999",
        "ShipperName":"W B EQUIPMENT",
        "ShipperCity":"WOOD RIDGE",
        "ShipperState":"NJ"
     },
     ]
   }
}

EDIT: I would like to try to use JSONDecoder, as it looks like a decent solution.

Would this work?

struct ShipmentStatusList: Decodable {
    let MobileAPIError: String
    let StatusList: StatusListItems

    enum CodingKeys : String, CodingKey {
        case MobileAPIError
        case StatusList
    }
}
struct StatusListItems{
    let ErrorMessage: String
    let Details: [Details]
}

struct Details {
    let Pro: String
    let BLNumber: String
    let ReferenceNumber: String
}

Upvotes: 1

Views: 2073

Answers (1)

vadian
vadian

Reputation: 285072

The value for key StatusList is a dictionary, please note the {}, the array is the value for key Details in statusList

if let parsedData = try JSONSerialization.jsonObject(with: data!) as? [String:Any],
   let statusList = parsedData["StatusList"] as? [String:Any],
   let details = statusList["Details"] as? [[String:Any]] {
       for detail in details {
          print(detail["Pro"])
       }
   }
}

And don't do things like (... as? ...)!, never!

The corresponding Codable structs are

struct Status: Codable {
    let mobileAPIError: String
    let statusList: StatusList

    enum CodingKeys: String, CodingKey { case mobileAPIError = "MobileAPIError", statusList = "StatusList" }
}

struct StatusList: Codable {
    let errorMessage: String
    let details: [Detail]

    enum CodingKeys: String, CodingKey { case errorMessage = "ErrorMessage", details = "Details" }
}

struct Detail: Codable {
    let pro, blNumber, referenceNumber, scac: String
    let carrier, shipperCode, shipperName, shipperCity: String
    let shipperState: String

    enum CodingKeys: String, CodingKey {
        case pro = "Pro", blNumber = "BlNumber", referenceNumber = "ReferenceNumber"
        case scac = "Scac", carrier = "Carrier", shipperCode = "ShipperCode"
        case shipperName = "ShipperName", shipperCity = "ShipperCity", shipperState = "ShipperState"
    }
}

do {
     let result = try JSONDecoder().decode(Status.self, from: data!)
     print(result)
} catch { print(error) }

Upvotes: 2

Related Questions