I am new on swift and I am getting a json back from a request but I can not parse. I am trying to get the json info and create coordinates to use on mapkit with annotations as well
Below is the json I get back
{
coord = [
{
islocationactive = 1;
latitude = "37.8037522";
locationid = 1;
locationsubtitle = Danville;
locationtitle = "Schreiner's Home";
longitude = "121.9871216";
},
{
islocationactive = 1;
latitude = "37.8191921";
locationid = 2;
locationsubtitle = "Elementary School";
locationtitle = Montair;
longitude = "-122.0071005";
},
{
islocationactive = 1;
latitude = "37.8186077";
locationid = 3;
locationsubtitle = "Americas Eats";
locationtitle = "Chaus Restaurant";
longitude = "-121.999046";
},
{
islocationactive = 1;
latitude = "37.7789669";
locationid = 4;
locationsubtitle = "Cheer & Dance";
locationtitle = Valley;
longitude = "-121.9829908";
}
] }
and my code to try to parse is this
let task = URLSession.shared.dataTask(with: request as URLRequest){
data, response, error in
//exiting if there is some error
if error != nil{
print("error is \(error)")
return;
}
//parsing the response
do {
//converting resonse to NSDictionary
var teamJSON: NSDictionary!
teamJSON = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary
print(teamJSON)
//getting the JSON array teams from the response
let liquidLocations: NSArray = teamJSON["coord"] as! NSArray
//looping through all the json objects in the array teams
for i in 0 ..< liquidLocations.count{
//getting the data at each index
// let teamId:Int = liquidLocations[i]["locationid"] as! Int!
}
} catch {
print(error)
}
}
//executing the task
task.resume()
but not that I try works. I want to get the latitude, longitude and create an annotationn on the map
Thanks for the help
You can try with below code its same as #Niko Adrianus Yuwono but made some changes so you will get teamid as integer
do {
let data : NSData = NSData() // change your data variable as you get from webservice response
guard let teamJSON = try NSJSONSerialization.JSONObjectWithData(data, options: []) as? [String: Any],
let liquidLocations = teamJSON["coord"] as? [[String: Any]]
else { return }
//looping through all the json objects in the array teams
for i in 0 ..< liquidLocations.count{
let teamId: Int = (liquidLocations[i]["locationid"] as! NSString).integerValue
print(teamId)
}
} catch {
print(error)
}
Try this
do {
guard let teamJSON = try JSONSerialization.jsonObject(with: data!, options: []) as? [String: Any],
let liquidLocations = teamJSON["coord"] as? [[String: Any]]
else { return }
//looping through all the json objects in the array teams
for i in 0 ..< liquidLocations.count{
let teamId: Int = (liquidLocations[i]["locationid"] as! NSString).integerValue
}
} catch {
print(error)
}
The key is not to use NSDictionary and NSArray because it's not strongly-typed (Although you can make it strongly-typed too) use Swift's array and Dictionary where you can use [Element Type] for array and [Key: Value] for dictionary
Related
how can I get applicationStateJson in below code, I can parse the bellow JSON object from data but can not able to get applicationStateJson from it
{
applicationStateJson = {
"address_status" = 0;
email = "xxxxxxxx;
"email_status" = 0;
"first_name" = xxx;
"last_name" = "";
"login_status" = 1;
loginstype = "<null>";
mobile = xxxxxx;
"mobile_status" = 1;
notifications = (
);
"notifications_size" = 0;
"otp_status" = 3;
"profile_id" = "<null>";
"profile_name" = "virtual_recruiter";
"user_id" = 454;
"user_status" = 1;
"virtual_recruiter_id" =xxx;
};
"error_msg" = "<null>";
status = "<null>";
}
code as
do {
let json = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableContainers) as AnyObject
print(json)
let applicationStateJson = try json["applicationStateJson"]
} catch { print(error.localizedDescription) }
Try with below code
First you need to change in below line, its Dictionary<String, Any> not an AnyObject
let json = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableContainers) as! Dictionary<String, Any>
And then get applicationStateJson by below code
if let appJson = json["applicationStateJson"] as? Dictionary<String, Any> {
print(appJson)
print("Email : \(appJson["email"] as? String ?? "Email not found")") // For get email
}
The root object of the JSON is a clearly a dictionary, not AnyObject (an object but I-have-no-idea-what-it-is).
The value for key applicationStateJson is a dictionary, too.
do {
if let json = try JSONSerialization.jsonObject(with: data) as? [String:Any],
let applicationStateJson = json["applicationStateJson"] as? [String:Any] {
print(applicationStateJson)
}
} catch {
print(error)
}
As always, .mutableContainers is completely meaningless in Swift
I'm trying to parse the JSON response below using the following code but can't seem to get it to work, how would I do this? Im trying to get "user_guid" and all the "entity_guid" in images.
SWIFT
do {
var entity_guid : Int = 0
var user_guid : Int = 0
let jsonResult = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableContainers) as? NSDictionary
// Parse JSON data
let jsonP = jsonResult?["result"] as! [AnyObject]
for jsonL in jsonP {
user_guid = jsonL["user_guid"] as! Int
entity_guid = jsonL["entity_guid"] as! Int
}
} catch {
}
JSON
{
"status":0,
"result":{
"user_guid":139219,
"images":[
{
"entity_guid":572356
},
{
"entity_guid":572354
},
{
"entity_guid":572352
}
]
}
}
Try below code:
do {
var entity_guid : Int = 0
var user_guid : Int = 0
let jsonResult = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as? [String:Any]
// Parse JSON data
let jsonP = jsonResult?["result"] as! [String:Any]
user_guid = jsonP["user_guid"] as! Int
let images = jsonP["images"] as! [[String:Int]]
for jsonL in images {
entity_guid = jsonL["entity_guid"]!
}
} catch {
print(error.localizedDescription)
}
Replace below code and try to check. You must use Swift datatypes wherever possible.
do {
var entity_guid : Int = 0
var user_guid : Int = 0
let jsonResult = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableContainers) as? [String: Any]
guard let jsonP = jsonResult["result"] as [String: Any] else {
return
}
user_guid = jsonP["user_guid"] as! Int
if let jsonArr = jsonP["images"] as? [String] {
for image in jsonArr {
entity_guid = image["entity_guid"] as! Int
}
}
How to get JSON format from array? This is my JSON formatter
{
"productName": "Lemonade",
"transaction": ["[2016-08-01 10:23:42] - Get product in warehouse",
"[2016-08-01 10:53:22] - Sent to customer"]
}
I have an error with this code. I don't know how to get JSON format from transaction array.
if let jsonObject = try JSONSerialization.jsonObject(with: returnData, options: .allowFragments) as? [String: AnyObject]
{
valSucceeded = (jsonObject["succeeded"] as? Bool)!;
valResponseCode = (jsonObject["responseCode"] as? String)!;
valResponseDescription = (jsonObject["responseDescription"] as? String)!;
valSerialNumber = (jsonObject["serialNumber"] as? String)!;
valProductName = (jsonObject["productName"] as? String)!;
if let transactionsArray = jsonObject["transactions"] as? Array<AnyObject> {
for transact in transactionsArray
{
if let transactionStr = transact["transactions"] as? String {
valTransactions = transactionStr
} else {
valTransactions = ""
}
}
}
let entryResult = TraceModel(succeeded: valSucceeded,
responseCode: valResponseCode,
responseDescription: valResponseDescription,
serialNumber: valSerialNumber,
productName: valProductName,
transactions: valTransactions);
traceArray.append(entryResult);
}
I have made the following function in Swift 3:
func parseJSON() {
var JsonResult: NSMutableArray = NSMutableArray()
do {
JsonResult = try JSONSerialization.jsonObject(with: self.data as Data, options:JSONSerialization.ReadingOptions.allowFragments) as! NSMutableArray
} catch let error as NSError {
print(error)
}
var jsonElement:NSDictionary=NSDictionary()
let locations: NSMutableArray = NSMutableArray()
for i in 0 ..< JsonResult.count
{
jsonElement = JsonResult[i] as! NSDictionary
let location = Parsexml()
if let title = jsonElement["Title"] as? String,
let body = jsonElement["Body"] as? String,
let userId = jsonElement["UserId"] as? Int,
let Id = jsonElement["Id"] as? Int
{
location.title = title
location.body = body
location.userId = userId
location.id = Id
}
locations.add(location)
}
DispatchQueue.main.async { () -> Void in
self.delegate.itemsDownloaded(items: locations)
}
When i call this function from another method, i get the following error:
Could not cast value of type '__NSArrayI' (0x105d4fc08) to 'NSMutableArray' (0x105d4fcd0).
It points me towards the element here:
JsonResult = try JSONSerialization.jsonObject(with: self.data as Data, options:JSONSerialization.ReadingOptions.allowFragments) as! NSMutableArray
Where it exits with a SIGBRT..
What have i missed here?
You are trying to convert an NSArray into an NSMutable array which is what the warning is complaining about.
Take the array it provides you, and then convert it into a mutable one.
let jsonArray = try JSONSerialization.jsonObject(with: self.data as Data, options:JSONSerialization.ReadingOptions.allowFragments) as! NSArray
jsonResult = jsonArray.mutableCopy() as! NSMutableArray
Unrelated, but you may also want to user a lower case value for the JsonResult to fit with normal iOS style guidelines. It should instead be jsonResult.
Another way to improve your code:
You are not mutating your JsonResult, so you have no need to declare it as NSMutableArray:
var JsonResult = NSArray()
do {
JsonResult = try JSONSerialization.jsonObject(with: self.data as Data, options:JSONSerialization.ReadingOptions.allowFragments) as! NSArray
} catch let error as NSError {
print(error)
}
And some steps to improve your code...
enum MyError: Error {
case NotArrayOfDict
}
func parseJSON() {
do {
guard let jsonResult = try JSONSerialization.jsonObject(with: self.data as Data) as? [[String: Any]] else {
throw MyError.NotArrayOfDict
}
let locations: NSMutableArray = NSMutableArray()
for jsonElement in jsonResult {
let location = Parsexml()
if let title = jsonElement["Title"] as? String,
let body = jsonElement["Body"] as? String,
let userId = jsonElement["UserId"] as? Int,
let Id = jsonElement["Id"] as? Int
{
location.title = title
location.body = body
location.userId = userId
location.id = Id
}
locations.add(location)
}
DispatchQueue.main.async { () -> Void in
self.delegate.itemsDownloaded(items: locations)
}
} catch let error {
print(error)
}
}
as! casting sometimes crashes your app, use it only when you are 100%-sure that the result is safely converted to the type. If you are not, using guard-let with as? is safer.
Use Swift types rather than NSSomething as far as you can.
Specifying .allowFragments is not needed, as you expect the result as an Array.
And if you can modify some other parts of your code, you can write your code as:
func parseJSON() {
do {
//If `self.data` was declared as `Data`, you would have no need to use `as Data`.
guard let jsonResult = try JSONSerialization.jsonObject(with: self.data) as? [[String: Any]] else {
throw MyError.NotArrayOfDict
}
var locations: [Parsexml] = [] //<-Use Swift Array
for jsonElement in jsonResult {
let location = Parsexml()
if let title = jsonElement["Title"] as? String,
let body = jsonElement["Body"] as? String,
let userId = jsonElement["UserId"] as? Int,
let Id = jsonElement["Id"] as? Int
{
location.title = title
location.body = body
location.userId = userId
location.id = Id
}
locations.append(location)
}
DispatchQueue.main.async { () -> Void in
self.delegate.itemsDownloaded(items: locations)
}
} catch let error {
print(error)
}
}
I am trying to access items parsed in JSON from the iTunes API using Swift 3.0, but I am struggling to access the objects after they have been parsed. The objects are being parsed in this format:
{
resultCount = 50;
results = (
{
artistId = 70936;
artistName = "Johnny Cash";
artistViewUrl = "https://itunes.apple.com/us/artist/johnny-cash/id70936?uo=4";
artworkUrl100 = "http://is2.mzstatic.com/image/thumb/Music3/v4/13/ae/73/13ae735e-33d0-1480-f51b-4150d4a45696/source/100x100bb.jpg";
artworkUrl30 = "http://is2.mzstatic.com/image/thumb/Music3/v4/13/ae/73/13ae735e-33d0-1480-f51b-4150d4a45696/source/30x30bb.jpg";
artworkUrl60 = "http://is2.mzstatic.com/image/thumb/Music3/v4/13/ae/73/13ae735e-33d0-1480-f51b-4150d4a45696/source/60x60bb.jpg";
collectionCensoredName = "The Essential Johnny Cash";
collectionExplicitness = notExplicit;
collectionId = 251001680;
collectionName = "The Essential Johnny Cash";
collectionPrice = "14.99";
collectionViewUrl = "https://itunes.apple.com/us/album/ring-of-fire/id251001680?i=251002253&uo=4";
country = USA;
currency = USD;
discCount = 2;
discNumber = 1;
isStreamable = 1;
kind = song;
previewUrl = "http://a1144.phobos.apple.com/us/r1000/070/Music/b3/99/be/mzi.qvkhtgfg.aac.p.m4a";
primaryGenreName = Country;
releaseDate = "2002-02-12T08:00:00Z";
trackCensoredName = "Ring of Fire";
trackCount = 18;
trackExplicitness = notExplicit;
trackId = 251002253;
trackName = "Ring of Fire";
trackNumber = 15;
trackPrice = "1.29";
trackTimeMillis = 155707;
trackViewUrl = "https://itunes.apple.com/us/album/ring-of-fire/id251001680?i=251002253&uo=4";
wrapperType = track;
},
I want to be able to access the information from all 50 results, such as the artistName, for instance. This is my parsing function attempting to get the artistName and add it to my NSDictionary, but it keeps returning that it can't unwrap the dictionary.
func parser() {
let enteredText:String = (tbxSearch.text?.replacingOccurrences(of: " ", with: "+"))!
let url = "https://itunes.apple.com/search?term=\(enteredText)"
print(url)
guard let urlRequest = URL(string: url) else
{
print("Error creating endpoint")
return
}
let request = URLRequest(url: urlRequest)
URLSession.shared.dataTask(with: request) {(data,response,error) in
do
{
guard let data = data else
{
return
}
guard let json = try JSONSerialization.jsonObject(with: data, options: []) as? NSDictionary else
{
return
}
if let results = json["results"] as? NSDictionary
{
self.avObjects.avDict.setValue("Artist Name", forKey: results["artistName"] as! String)
print(self.avObjects.avDict)
}
else
{
print("Couldn't unwrap the dictionary.")
}
print(json)
}
catch let error as NSError
{
print(error.debugDescription)
}
}.resume()
}
It looks like results is an array of dictionaries, not just a dictionary.
Instead of this: if let results = json["results"] as? NSDictionary
try this: if let results = json["results"] as? NSArray
You could then map or iterate over each element in the array, extracting "artistName" from each one, for example.
results is an array of dictionaries, not a dictionary itself. Try changing this:
if let results = json["results"] as? NSDictionary
to:
if let results = json["results"] as? NSArray
and then iterating over results. Each element of results is a dictionary with attributes such as artistName.