This is the response that I get from an API call. I wanted to decode the JSON data that I receive. How do I go about with the structure "list" in the response?
The standard way of doing this is to declare structs that match your JSON and make them Codable
. The compiler then deals with all the details required to encode and decode the JSON. There’s tonnes of info about this out there on the ’net, but as an Apple person I’m going to point you to Apple resources (-:
To make this concrete, here’s some test code inspired by your example:
let json = """
{
"total": 1,
"list": [
{
"lockId": 12345
},
{
"lockId": 54321
}
]
}
"""
struct Response: Codable {
var total: Int
var list: [ListElement]
}
struct ListElement: Codable {
var lockId: Int
}
let jsonData = Data(json.utf8)
let response = try JSONDecoder().decode(Response.self, from: jsonData)
print(response.list[1].lockId) // -> 54321
ps It helps if you post the text of your data rather than a screen shot; that way folks can copy’n’paste it into a test project.
Share and Enjoy
Quinn “The Eskimo!” @ DTS @ Apple
Thank you so much for you reply. And the resource links. Will check them out
struct locks: Codable {
var list : [lists]
let pageNo : Int
let pageSize: Int
let pages: Int
let total : Int
}
struct lists: Codable {
let lockId : Int
let date : Int
let lockName : String
let lockAlias : String
let lockMac : String
let electricQunatity : Int
let keyboardPwdVersion : Int
let specialValue : Int
}
let dataAsString = String(data: data!, encoding: String.Encoding.utf8)
print(dataAsString!)
let users = try? JSONDecoder().decode(locks.self, from: data!)
print(users)
Here, data is the URL data that I receive.
This is the output that I am receiving.
The nil value is when I print "users" and the list is the value of "dataAsString"
{"list":[{"lockId":1272137,"date":1553078256000,"specialValue":21731,"electricQuantity":15,"lockAlias":"A","keyboardPwdVersion":4,"lockMac":"E9:45:BA:7B:ED:28","lockName":"S202C_28ed7b"}],"pageNo":1,"pageSize":10000,"pages":1,"total":1} nil
Try this
do {
let users = try JSONDecoder().decode(locks.self, from: data!)
print(users)
} catch {
print(error)
}
You will get
keyNotFound(CodingKeys(stringValue: "electricQunatity", intValue: nil), Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "list", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0)], debugDescription: "No value associated with key CodingKeys(stringValue: \"electricQunatity\", intValue: nil) (\"electricQunatity\").", underlyingError: nil))
struct list: Codable {
let electricQunatity : Int // but your data is {"electricQuantity":15}
}
Hi,
Instead of:
Write instead:
do {
let users = try JSONDecoder().decode(locks.self, from: data!)
print(users)
} catch {
print(error)
}
Run it: it will print an error message. Read this error message carefully, because it tells what is wrong. It will help you fix the error.
Generally speaking, avoid try?
when you are debugging some code, because try?
hides errors away, and just give you back a plain nil
which does not tell you what has turned wrong. Instead, use try
, catch errors, and look at them, because this is generally where the solution is.
We had the same idea :-)
Thank you! This worked!
Seems like you got this working. Yay!
One follow-up point regarding this:
struct locks: Codable {
…
}
struct lists: Codable {
…
}
In Swift we generally start types with an uppercase letter. So locks
would become Locks
, and so on.
If you’re curious about the details here, check out the Swift API Design Guidelines.
Share and Enjoy
Quinn “The Eskimo!” @ DTS @ Apple