So I tried to parse a json file and when I parse it as per the syntax, it gives me an error that cannot change the string to an array of dictionary, but when I fix the problem, it generates nil. Can anyone give an opinion
func jsonFour() {
let string = "[{\"address\": 7023000630,\"reportStatus\": \"Retrieved\",\"currentLocation\": {\"latitude\": 29.8529, \"longitude\": 73.99332,\"timestamp\": \"2019-01-07T16:35:25.079+05:30\"} }, {\"address\": 7290098339, \"reportStatus\": \"Retrieved\", \"currentLocation\": {\"latitude\": 21.628569, \"longitude\": 72.996956,\"timestamp\": \"2019-01-07T16:35:25.079+05:30\" } } ]"
let data = string.data(using: .utf8)!
do {
if let jsonArray = try JSONSerialization.jsonObject(with: data, options : JSONSerialization.ReadingOptions.mutableContainers) as? [[ String : Any ]]
{
print(jsonArray) // use the json here
let address = jsonArray["address"] as! [[String:Any]]
if let timestamp = address["timestamp"] as? [String]{print(timestamp)}
} else {
print("bad json")
}
} catch let error as NSError {
print(error)
}
}
When I remove the double brackets from "String : Any", it runs fine, but does not give any value but nil.
And when I proceed with this way, it skips the if statement and just prints "bad json".
What am I doing wrong here?
Since there is Codable, I would strongly recommend you to using it instead of JSONSerialization.
So start with declaring your structs to match with your JSON struct
struct Model: Codable {
var address: Int
var reportStatus: String
var currentLocation: Location
}
struct Location: Codable {
var latitude, longitude: Double
var timestamp: String
}
Now just decode your JSON using JSONDecoder
do {
let data = string.data(using: .utf8)!
let models = try JSONDecoder().decode([Model].self, from: data)
} catch {
print(error)
}
... now models is array of Model objects and you can work with it.
For sure you should use Codable for this , but for your code to run use
let string = "[{\"address\": 7023000630,\"reportStatus\": \"Retrieved\",\"currentLocation\": {\"latitude\": 29.8529, \"longitude\": 73.99332,\"timestamp\": \"2019-01-07T16:35:25.079+05:30\"} }, {\"address\": 7290098339, \"reportStatus\": \"Retrieved\", \"currentLocation\": {\"latitude\": 21.628569, \"longitude\": 72.996956,\"timestamp\": \"2019-01-07T16:35:25.079+05:30\" } } ]"
let data = string.data(using: .utf8)!
do {
if let jsonArray = try JSONSerialization.jsonObject(with: data) as? [[ String : Any ]]
{
jsonArray.forEach {
if let add = $0["address"] as? Int , let currentLocation = $0["currentLocation"] as? [String:Any], let timestamp = currentLocation["timestamp"] as? String
{
print("address is : ", add ,"timestamp is : " , timestamp)
}
}
} else {
print("bad json")
}
} catch {
print(error)
}
Your obvious problem is here
let address = jsonArray["address"] as! [[String:Any]]
jsonArray is an array that you can't subscript with ["address"]
An array is a list. It can contain multiple items. You have to use a loop to iterate an array (like in your previous question)
address is Int (no double quotes).The value for key timestamp is String and is in the dictionary for key currentLocation in the array
let data = Data(string.utf8)
do {
if let jsonArray = try JSONSerialization.jsonObject(with: data) as? [[String : Any]]
{
print(jsonArray) // use the json here
for item in array {
let address = item["address"] as! Int
let currentLocation = item["currentLocation"] as! [String:Any]
let timestamp = currentLocation["timestamp"] as! String
print(timestamp)
}
} else {
print("bad json")
}
} catch {
print(error)
}
Never use .mutableContainers in Swift. It's pointless.