Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift 4 decoding json using Codable

Tags:

swift4

codable

Can someone tell me what I'm doing wrong? I've looked at all the questions on here like from here How to decode a nested JSON struct with Swift Decodable protocol? and I've found one that seems exactly what I need Swift 4 Codable decoding json.

{
"success": true,
"message": "got the locations!",
"data": {
    "LocationList": [
        {
            "LocID": 1,
            "LocName": "Downtown"
        },
        {
            "LocID": 2,
            "LocName": "Uptown"
        },
        {
            "LocID": 3,
            "LocName": "Midtown"
        }
     ]
  }
}

struct Location: Codable {
    var data: [LocationList]
}

struct LocationList: Codable {
    var LocID: Int!
    var LocName: String!
}

class ViewController: UIViewController {

override func viewDidLoad() {
    super.viewDidLoad()

    let url = URL(string: "/getlocationlist")

    let task = URLSession.shared.dataTask(with: url!) { data, response, error in
        guard error == nil else {
            print(error!)
            return
        }
        guard let data = data else {
            print("Data is empty")
            return
        }

        do {
            let locList = try JSONDecoder().decode(Location.self, from: data)
            print(locList)
        } catch let error {
            print(error)
        }
    }

    task.resume()
}

The error I am getting is:

typeMismatch(Swift.Array, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode Array but found a dictionary instead.", underlyingError: nil))

like image 851
Misha Avatar asked Sep 16 '17 05:09

Misha


People also ask

How do I parse JSON in Codable Swift?

To do this, you have to convert your Swift objects to JSON. This is called encoding. To decode or encode data, your objects must conform to the Codable protocol. Then you can use JSONDecoder() or JSONEncoder() objects to decode/encode the data.

What does Codable mean in Swift?

Codable is the combined protocol of Swift's Decodable and Encodable protocols. Together they provide standard methods of decoding data for custom types and encoding data to be saved or transferred.

What is the difference between Codable and Decodable in Swift?

Understanding what Swift's Codable isWhen you only want to convert JSON data into a struct, you can conform your object to Decodable . If you only want to transform instances of your struct into Data , you can conform your object to Encodable , and if you want to do both you can conform to Codable .


1 Answers

Check the outlined structure of your JSON text:

{
    "success": true,
    "message": "got the locations!",
    "data": {
      ...
    }
}

The value for "data" is a JSON object {...}, it is not an array. And the structure of the object:

{
    "LocationList": [
      ...
    ]
}

The object has a single entry "LocationList": [...] and its value is an array [...].

You may need one more struct:

struct Location: Codable {
    var data: LocationData
}

struct LocationData: Codable {
    var LocationList: [LocationItem]
}

struct LocationItem: Codable {
    var LocID: Int!
    var LocName: String!
}

For testing...

var jsonText = """
{
    "success": true,
    "message": "got the locations!",
    "data": {
        "LocationList": [
            {
                "LocID": 1,
                "LocName": "Downtown"
            },
            {
                "LocID": 2,
                "LocName": "Uptown"
            },
            {
                "LocID": 3,
                "LocName": "Midtown"
            }
        ]
    }
}
"""

let data = jsonText.data(using: .utf8)!
do {
    let locList = try JSONDecoder().decode(Location.self, from: data)
    print(locList)
} catch let error {
    print(error)
}
like image 53
OOPer Avatar answered Dec 29 '22 23:12

OOPer