Swift parsing json doesn't work - ios

I want to parse a json file, this is in my json file:
{
"currentPowerByClient": 0, <- i want to read this
"currentPowerToClient":518,
"tariff":1,
"totalGasDelivered":1061.004,
"totalPowerByClientHigh":10.704,
"totalPowerByClientLow":23.042,
"totalPowerToClientHigh":912.221,
"totalPowerToClientLow": 693.499
}
this is my swift code, the object called JSONResult contains my JSON code
var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(data, options:
NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary
if let item = jsonResult as NSDictionary? {
if let currentPowerByClient = item["currentPowerByClient"] as? NSDictionary {
println(currentPowerByClient)
}
}
when i run it, it doesn't print anything

The line
if let currentPowerByClient = item["currentPowerByClient"] as? NSDictionary
should be
if let currentPowerByClient = item["currentPowerByClient"] as? NSNumber
because item["currentPowerByClient"] is expected to be a number, not a dictionary. it works then

Related

Swift parse JSON formatting

I created an API that has a JSON response in the following format:
[{"name":"xxx","direct_link":"http:\/\/domain.com\/images\/xxx.png","image":"http:\/\/domain.com\/images\/xxx.png"},{"name":"yyy","direct_link":"http:\/\/domain.com\/images\/yyy.png","image":"http:\/\/domain.com\/images\/yyy.png"}]
Notice how the JSON response has no array title.
My Swift code looks like this:
do {
//converting resonse to NSDictionary
var teamJSON: NSDictionary!
teamJSON = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers) as? NSDictionary
//getting the JSON array teams from the response
let teams: NSArray = teamJSON["teams"] as! NSArray
//looping through all the json objects in the array teams
for i in 0 ..< teams.count{
//getting the data at each index
let teamId:Int = teams[i]["name"] as! String!
let teamName:String = teams[i]["direct_link"] as! String!
let teamMember:Int = teams[i]["image"] as! Int!
//displaying the data
print("name -> ", teamId)
print("direct_link -> ", teamName)
print("image -> ", teamMember)
print("===================")
print("")
}
Notice how the array is looking for a title "teams". How can I ensure the JSON is properly parsed and displays the 3 values I need for the JSON response? I'm new to app coding and have a web background, still trying to wrap my head around this.
As it stands when I try to build and run I get the following error: fatal error unexpectedly found nil while unwrapping an optional value
Try this:
do {
guard let teams = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers) as? NSArray else {
//Doesn't exist, or isn't an NSArray
return
}
for team in teams {
//getting the data at each index
let teamId = team["name"] as! String
let teamName = team["direct_link"] as! String
let teamMember = team["image"] as! Int
//displaying the data
print("name -> ", teamId)
print("direct_link -> ", teamName)
print("image -> ", teamMember)
print("===================")
print()
}
}
//...
Some notes:
Don't cast to implicitly unwrapped optionals (e.g. String!)
Don't add unnecessary type annotations
Use guard let to enforce preconditions (e.g. the JSON isn't nil, and is castable to NSArray).
Prefer iterating over elements of an Array (for team in teams) over iterating a range (for i in 0..<teams.count)
If you need only the indices, use for i in teams.indices
If you need the indices and elements, use for (index, team) in teams.enumerate()
The problem is this line:
teamJSON = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers) as? NSDictionary
because you are trying to cast a JSON array to a dictionary.
Just use
teamJSON = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers) as? NSArray
And then you also won't need to do this:
//getting the JSON array teams from the response
let teams: NSArray = teamJSON["teams"] as! NSArray
Because teamJSON is already the array.
I think the key issue you have to be aware of is that NSJSONSerialization.JSONObjectWithData() can return either an NSDictionary OR an NSArray, depending on whether the root level data in the JSON is an array or a dictionary.
ISSUE:
Your NSJSONSerialization.JSONObjectWithData would return an NSArray and not NSDictionary
SOLUTION:
Update code as below:
var teamJSON = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers) as? NSArray
//getting the JSON array teams from the response
let teams: NSArray = teamJSON
ALSO
Don't force cast values using !
Always cast it as optional using ?

Swift 2 parse Json as Optional to array

I am getting list of countries from a web service. After receiving it I used this code to process it:
if let json = try NSJSONSerialization.JSONObjectWithData(data!, options: []) as? NSDictionary {
// triggering callback function that should be processed in the call
// doing logic
} else {
if let json = try NSJSONSerialization.JSONObjectWithData(data!, options:[]) as? AnyObject {
completion(json)
} else {
let jsonStr = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("Error could not parse JSON string: \(jsonStr)")
}
}
And after that list looks like this (it ends up in this part NSJSONSerialization.JSONObjectWithData(data!, options:[]) as? AnyObject) :
Optional((
{
"country_code" = AF;
"dial_code" = 93;
id = 1;
name = Afghanistan;
},
{
"country_code" = DZ;
"dial_code" = 213;
id = 3;
name = Algeria;
},
{
"country_code" = AD;
"dial_code" = 376;
id = 4;
name = Andorra;
}
))
I should now convert this json object to array (or NSDictionary somehow) and to loop through it. Can someone advice how?
Currently you can't loop through your object because it has been cast as AnyObject by your code. With your current code you're casting the JSON data either as? NSDictionary or as? AnyObject.
But since JSON always start with a dictionary or an array, you should do this instead (keeping your example):
if let json = try NSJSONSerialization.JSONObjectWithData(data!, options: []) as? NSDictionary {
// process "json" as a dictionary
} else if let json = try NSJSONSerialization.JSONObjectWithData(data!, options:[]) as? NSArray {
// process "json" as an array
} else {
let jsonStr = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("Error could not parse JSON string: \(jsonStr)")
}
And ideally you would use Swift dictionaries and arrays instead of Foundation's NSDictionary and NSArray, but that is up to you.
try this
let jsonDictionary = try NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers) as? [String:AnyObject]

Swift JSON error : Could not cast value of type '__NSDictionaryM' to 'NSArray'

when decoding JSON from webservice(API) i get error :
Could not cast value of type '__NSDictionaryM' (0x1037ad8a8) to 'NSArray' (0x1037ad470).
My Code :
var kGetURL = "http://bitnami.local/cscart_demo/api/users"
//var kGetURL = "http://localhost/fendy/getjson.php"
var json : Array<AnyObject> = []
override func viewDidLoad() {
super.viewDidLoad()
start()
}
func getData(data : NSData){
//error at this line :
json = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as! Array<AnyObject>
//error
tableView.reloadData()
}
func start(){
var url : NSURL = NSURL(string: kGetURL)!
var data : NSData = NSData(contentsOfURL: url)!
getData(data)
}
if i change url to http://localhost/fendy/getjson.php, its working so nice.
i get error if my url is http://bitnami.local/cscart_demo/api/users
Response from webservice http://localhost/fendy/getjson.php :
[{"id":"17","Name":"KFC","Message":"awesome"},
{"id":"18","Name":"McDonald","Message":"good"},
{"id":"23","Name":"Burger King","Message":"tasty"},
{"id":"38","Name":"Pizza hut","Message":"yummy"},
{"id":"39","Name":"Steak","Message":"very Delicious"}]
Response from webservice http://bitnami.local/cscart_demo/api/users :
{"users":
[{"user_id":"4","user_login":"user_4","is_root":"N","timestamp":"1441608048","user_type":"C","status":"A","firstname":"","lastname":"","email":"fendy.w#mvig.net","company":"","company_id":"1","company_name":"Simtech"},
{"user_id":"3","user_login":"customer","is_root":"N","timestamp":"1441604240","user_type":"C","status":"A","firstname":"Customer","lastname":"Customer","email":"customer#example.com","company":"Simtech","company_id":"1","company_name":"Simtech"},
{"user_id":"1","user_login":"admin","is_root":"Y","timestamp":"1441604240","user_type":"A","status":"A","firstname":"John","lastname":"Doe","email":"robby#mvig.net","company":"Your company","company_id":"0","company_name":null}],
"params":{"page":1,"items_per_page":"10","sort_order":"asc","sort_by":"name","sort_order_rev":"desc","total_items":"3"}}
i think it's Style is same, but why not working with url http://bitnami.local/cscart_demo/api/users . anyone can help?
The bitnami response starts with a { and it is therefore a JSON object, which corresponds to an NSDictionary. The other one starts with [ which indicates an array.
You need to change the type of json to Dictionary<String, AnyObject>, and deserialize as follows:
json = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as! Dictionary<String, AnyObject>
Your method is casting JSON result to an array. It works fine with the URL that returns an array represented as JSON, but it does not work with the URL that returns a dictionary, not an array, represented as JSON.
Although the "style" of returned values looks the same, the second one is a one-item dictionary. What you probably want is to extract the "users" element from it, which is an array.
If you do not know which of the two URLs you are getting, you could try both styles with as? cast instead of as!:
let tmp : AnyObject! = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil)
if let arr = tmp as? Array<AnyObject> {
json = arr
} else if dict = tmp as? [String: AnyObject] {
json = dict["users"] as! Array<AnyObject>
} else {
// Handle an error: the input was unexpected
}
tableView.reloadData()
try cache for Serialization
do {
if let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String : Any] { // as? data type
if let otherDict = json["dataKey"] as? [String : Any] {
//do something
}
}
} catch {
// can't json serialization
}

Check for http response format

I am making http call and receiving JSON response
var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &err) as! NSDictionary
But when not receiving actual json this line fail with error cannot cast value of NSArray to NSDictionary
I understand why this happen my question is how to properly check what format is the response
I do like this in my api's:
typealias JSONType = (dictionary: [String:AnyObject]?, array: [AnyObject]?)
var error:NSError?
var json:AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: &error)
if let dict = json as? [String:AnyObject] {
return (dict, nil)
}
else if let arr = json as? [AnyObject] {
return (nil, arr)
}
So when I return that JSONType I can change to use it as a dictionary or array by just:
json.array

Unable to get the value of JSON - Swift

I tried to get the value of "seed" from json response. But i am getting nil.
Json Response:
{
"response": {
"params": {
"rows": "20",
"defType": "abc",
"seed": "381786611"
}
}
}
Swift Parsing:
if let responseHeader:AnyObject = object?["response"] as? NSDictionary {
if let t = (responseHeader["params"] as? NSDictionary){
let t1 = t["seed"] as? String
println("result is \(t1)") // This returns nil
}
}
Json Parsing
func processJsonToDictionary(object:AnyObject?) -> AnyObject?{
if object != nil {
if let data: AnyObject = object {
var parseError: NSError?
var jsonResult = NSJSONSerialization.JSONObjectWithData(object as NSData!, options: NSJSONReadingOptions.MutableContainers, error: &parseError) as? NSDictionary
if(parseError != nil){
return parseError
}
else{
return jsonResult
}
}
}
return nil
}
I am not able to get the value of t1. it always returns nil.
How can i get the value.
Also, I put a breakpoint and tried to print the value of t1. But the Xcode Keeps crashing. Why?
I think the major problem here is only accessing a JSON object in swift.
var error: NSError?
let jsonDict = NSJSONSerialization.JSONObjectWithData(jsonData, options: nil, error: &error) as NSDictionary
let resp = jsonDict["response"] as? NSDictionary
let params = resp?["params"]?["seed"]
let seed = params!! as NSString
This is just to show you how a JSON object is accessed in swift. You can ofcourse change it according to your needs to remove unwanted Optional Chaining.
For easy JSON manipulation in Swift you could try this little library. It seems pretty easy and you could do this:
var dictionary: [String: AnyObject]!
if let json = NKJSON.parse(yourNSDataObject) {
dictionary <> json[NKJSON.rootKey]
}
First confirm that the response which you are getting is in json format or in string format.
For json parsing you can use swifty json pod

Resources