Can' read JSON element in Swift - json

I'm using Swift 3.0 and cannot seem to parse this JSON response.
{
"books": [{
"name": "NAME",
"key": "Key"
}],
"count": 1
}
Here is what I am using
let booksData = try JSONSerialization.jsonObject(with: data!) as! [String:Any]
if let bookCount = booksData["count"] as? String {
print("found")
}
else {
print("Not Found")
}
I must be missing something really obvious here. I'm trying to read count before reading the array of books.

Try this:
if let bookCount = booksData["count"] as? NSNumber {
print("found")
} else {
print("Not Found")
}
In your JSON data, see "count": 1. The value 1 is a JSON number, which is converted to NSNumber with JSONSerialization. And as? casting from NSNumber to String always fails.

if let bookCount = bookData should be if let bookCount = booksData

Related

How to access varying JSON key in Swift 4.2 natively?

I have the following dummy JSON data for a bus to school.
{
"toSchool": {
"weekday": [{
"hour": 7,
"min": 10,
"type": null,
"rotary": false
}],
"sat": [{
"hour": 8,
"min": 15,
"type": null,
"rotary": true
}]
}
}
I would like to access "weekday" and "sat" key with a variable based on user input. How can I achieve this natively?
Using SwiftyJSON, it is fairly simple like below
let json = try JSON(data: data)
let userDirection = "shosfc"
let userWeek = "weekday"
let busList = json[userDirection][0][userWeek]
However, I was wondering how this would be done natively to remove dependencies.
It seems that CodingKey and enum might be the way to handle this. When the example is as simple as this, I can understand. However, I just cannot get my head around it for my particular usage where it involves custom objects not just String.
How can I do this? Please help.
This is based on your earlier question
func bus(isWeekday: Bool = true) -> [Bus] {
return isWeekday ? shosfc.weekDay : shosfc.sat
}
I think code that below will work:
struct SampleResponse: Codable {
let toSchool: ToSchool
}
struct ToSchool: Codable {
let weekday, sat: [Sat]
}
struct Sat: Codable {
let hour, min: Int
let type: String?
let rotary: Bool
}
To decode this type of response, you must decode this JSON with SampleResponse type.
let sampleResponse = try? newJSONDecoder().decode(SampleResponse.self, from: jsonData)
After that, you can reach variables like you asked.
You can convert JSON string to Dictionary in swift and access it the same way you just did:
func parseToDictionary(_ jsonStr: String) -> [String: Any]? {
if let data = jsonStr.data(using: .utf8) {
do {
return try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
} catch {
print(error.localizedDescription)
}
}
return nil
}
let jsonStr = "{Your JSON String}"
let json = parseToDictionary(jsonStr)
let userDirection = "shosfc"
let userWeek = "weekday"
let busList = json[userDirection][0][userWeek]

Parse JSON Data Array with Swift 4

I am using the following code. It only works if the JSON data does not start with a '[' character. It works fine for JSON data starting with a '{' character. There is a similar question here: Parsing JSON array in swift but most of the methods are deprecated and I was unable to get the code to work. Here is the JSON call I am using:
guard let json = (try? JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableContainers)) as? [String: Any] else {
print("Error: Could not parse JSON!!!")
return
}
I tried removing all options and using allowFragments and mutableLeaves among others. From what I understand mutableContainers is a default setting but I have been trying whatever I can. Any help or advice would be much appreciated.
Here is a sample of the JSON data I am working with:
{ "CREATED_BY" = "Domain\USER"; "CREATED_DATE" = "2011-09-30T15:00:13"; STATUS = U; "EMPLOYEE_NUMBER" = 039000292; "UPDATED_BY" = "Domain\USER""; "UPDATED_DATE" = "2014-08-02T13:22:01"; }
The issue is that the [] signifies that the json is an Array of objects, so you need to cast this to an array. You can do this by either casting it to [Any] or by casting it to an array of dictionaries (which is what it really is).
do {
let json = try JSONSerialization.jsonObject(with: data, options: []) as? [Any]
let json2 = try JSONSerialization.jsonObject(with: data, options: []) as? [[String: Any]]
} catch {
print("Error: Couldn't parse JSON. \(error.localizedDescription)")
}
So provided the following json to the above block:
let jsonString = """
[{
"id": "5",
"name": "Test",
"team1": "thingy team",
"team2": "clicky team",
"category": "4",
"end_date": "1415217600",
"cat_name": "new thingy",
"team1_bets": 1,
"team2_bets": 1
}]
"""
you would end up with an output of the following:
let json = Optional([{
"cat_name" = "new thingy";
category = 4;
"end_date" = 1415217600;
id = 5;
name = Test;
team1 = "thingy team";
"team1_bets" = 1;
team2 = "clicky team";
"team2_bets" = 1;
}])
let json2 = Optional([["team2_bets": 1, "name": Test, "id": 5, "team1_bets": 1, "team2": clicky team, "team1": thingy team, "category": 4, "cat_name": new thingy, "end_date": 1415217600]])
The main difference between the two is that the contents of json are an array of Any objects, which would then need to be cast to whatever data type you're working with. The json2 array is an array of dictionaries, which you would then need to cast the Any objects but you still have the keys available.
Then it may be an array
do {
let json = try JSONSerialization.jsonObject(with: data) as? [Any]
print(json)
}
catch {
print(error)
}
This [ ] means Array ---- > [Any]
while this { } means Dictionary -----> [String:Any]
let json = try JSONSerialization.jsonObject(with: data!) as? [NSDictionary]; //jsonArray
print(json![0].value(forKey: "name")!); //jsonObject

Swift3 JSON using Alamofire

I'm new to Alamofire and Swift.
Now, I'm trying to convert JSON from the API, but I don't know how to convert it.
API like this :
[
{
"myid": "10303210302003",
"mySubid": "10303210302003",
"area_pkid": "3"
},
{
"myid": "10303210302004",
"mySubid": "10303210302004",
"area_pkid": "4"
},
....]
I'm so confused about "[" and "]" , I don't know how to convert it and get myid.
Here is my code
Alamofire.request(MyURL, method: .get).responseJSON { (response) in
guard let totalJSON = response.result.value as? [String : Any] else { return } // My code is just return !! WHY??
}
It's simply
guard let totalJSON = response.result.value as? [[String : Any]] else { return }
for item in totalJSON {
print(item["myid"] as? String ?? "n/a")
}
since the enclosing object is an array ([])
You can even cast the array to [[String:String]] if all values are String
Yep, [] is an array and {} represents as Dictionary. So to get myid just do:
guard let totalJSON = response.result.value as? [Any] else { return }
if let i = a["myID"] as? String, let a = totalJSON[0] as? [String: Any]
{
print(i)
}

Swift JSON parsing

I am working on an iOS weather app and need some help getting some values with JSON. I am trying to pull the value of id in the weather object. I am getting a value of nil when I debug. Could someone please help me with the logic? Here is the JSON request and Swift code.
{
"coord":{
"lon":138.93,
"lat":34.97
},
"weather":[
{
"id":800,
"main":"Clear",
"description":"clear sky",
"icon":"01n"
}
],
"base":"cmc stations",
"main":{
"temp":292.181,
"pressure":1005.21,
"humidity":100,
"temp_min":292.181,
"temp_max":292.181,
"sea_level":1014.59,
"grnd_level":1005.21
},
"wind":{
"speed":3.41,
"deg":78.0005
},
"clouds":{
"all":0
},
"dt":1464801034,
"sys":{
"message":0.003,
"country":"JP",
"sunrise":1464723086,
"sunset":1464774799
},
"id":1851632,
"name":"Shuzenji",
"cod":200
}
Here is my Swift snippet:
let requestURL: NSURL = NSURL(string: "http://api.openweathermap.org/data/2.5/weather?lat=35&lon=139&appid=6361e893fa064b1bfeaca686cd0929cc")!
let urlRequest: NSMutableURLRequest = NSMutableURLRequest(URL: requestURL)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(urlRequest) {
(data, response, error) -> Void in
let httpResponse = response as! NSHTTPURLResponse
let statusCode = httpResponse.statusCode
if (statusCode == 200) {
print("JSON Downloaded Sucessfully.")
do{
let json = try NSJSONSerialization.JSONObjectWithData(data!, options:.AllowFragments)
if let today = json["weather"] as? [[String: AnyObject]] {
//this is pulling 4 key value pairs
for weather in today {
let id = weather["id"] as? String
self.trumpDescription.text=id;
print(id)
}
}
}
catch {
print("Error with Json: \(error)")
}
}
}
task.resume()
}
The problem lies in your cast to a string. If you do not cast the id as a String, it will print "800" as an Int.
When you are grabbing the id from the json and converting it to a string, it reads the string and includes the new line character.
I played around in the playground
So you are correctly getting to the spot in the json, but you need to unwrap your optional.
You can also use the nil coalescing operator to unwrap optionals so you don't have to have a bunch of if lets:
let id = weather["id"] as? String ?? ""
Which will either set id to the value or to "" if it doesn't exist.
try this in your code:
let id = weather["id"]?.stringValue
instead of this:
let id = weather["id"] as? String
And see the magic!
Edit for explanation:
As this answer worked for you, let me tell you why it did.
The id is being sent as integer from the server side. When you do weather["id"] it returns object of type AnyObject?. When you do weather["id"] as? String the casting fails thus you were getting nil.

Get data from json array swift 2

I'm trying to get data drom the json array, this is the code that i'm trying, the thing is that i would like to get only the name that is inside this json
{
"tag": "getuser",
"success": 1,
"error": 0,
"uid": "56108b7e651ad2.95653404",
"user": {
"name": "2",
"phone": "2",
"email": "2"
}
}
I tryied this
let jsonData:NSDictionary = try NSJSONSerialization.JSONObjectWithData(urlData!, options:NSJSONReadingOptions.MutableContainers ) as! NSDictionary
let name = jsonData["user"]
print("Nombre del usuarioes: \(name)")
But this prints the whole user data, name, phone and email, how can i be able to print only the name or only the email?
You don't have to use a library and you don't have to use key-value coding.
The same way you're already using subscripting for your dictionary with this:
let name = jsonData["user"]
you just have to continue subscripting to find your value.
Example:
do {
let jsonData = try NSJSONSerialization.JSONObjectWithData(urlData!, options: []) as! NSDictionary
let user = jsonData["user"]!
let name = user["name"]
print(name)
} catch {
print(error)
}
Even better with safe unwrapping:
do {
if let data = urlData, let jsonData = try NSJSONSerialization.JSONObjectWithData(data, options: []) as? NSDictionary {
if let user = jsonData["user"] as? NSDictionary, let name = user["name"] as? String {
print(name)
}
}
} catch {
print(error)
}
Note: in JSON, a dictionary is defined by {} and an array is defined by []. What you have here is a dictionary containing a dictionary, not an array (cf your question title).
A great library to decode json is SwiftyJSON
you can get sub-scripted data from the json like so
import SwiftyJSON
if let dataFromString = jsonString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false) {
let json = JSON(data: dataFromString)
let name = json["user"]["name"].string
print(name)
}
Use your code, then get the field from jsonData by this:
let name = jsonData.valueForKeyPath("user.name") as! String
let email = jsonData.valueForKeyPath("user.email") as! String