NSJSONSerialization.JSONObjectWithData Returns nil - ios

[
{
"_id": "557f27522afb79ce0112e6ab",
"endereco": {
"cep": "asdasd",
"numero": "asdasd"
},
"categories": [],
"name": "teste",
"hashtag": "teste"
}
]
Returns nil without error :
var json = NSJSONSerialization.JSONObjectWithData(data, options:NSJSONReadingOptions.AllowFragments, error: &erro) as? NSDictionary

It's returning nil without error because it's not the JSON parsing that's failing. It's failing because of the conditional type cast of the resulting object as a dictionary. That JSON doesn't represent a dictionary: It's an array with one item (which happens to be a dictionary). The outer [ and ] indicate an array. So, when you parse this, you want to cast it as a NSArray.
For example, in Swift 1.2 you could:
if let json = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: &error) as? NSArray, let dictionary = json.firstObject as? NSDictionary {
println(dictionary)
} else {
println(error)
}
Or you could cast it as an array of dictionaries:
if let json = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: &error) as? [[String: AnyObject]], let dictionary = json.first {
println(dictionary)
} else {
println(error)
}

Calling isValidJSONObject: or attempting a conversion are the definitive ways to tell if a given object can be converted to JSON data.
isValidJSONObject(_:)
Returns a Boolean value that indicates whether a given object can be converted to JSON data.
Declaration
SWIFT
class func isValidJSONObject(_ obj: AnyObject) -> Bool
Parameters
obj
The object to test.
Return Value
true if obj can be converted to JSON data, otherwise false.
Discussion
Availability
Available in iOS 5.0 and later.

Related

Iterate through a JSON named array of dictionaries with swift 2.1

I'm pulling a JSON array of dictionaries trying to add them to a class I created and use them for a UITableView. The JSON would look like this:
{
"inventory":[
{
"item":"item 1",
"description":"item 1 description",
"quantityOnHand":"42",
"supplier_id":"1",
"supplierName":"Supplier 1"
},
{
"item":"item 2",
"description":"item 2 description",
"quantityOnHand":"1001",
"supplier_id":"1",
"supplierName":"Supplier 1"
} ...
and so on...
I'm grabbing all this in my viewDidLoad() and trying to add each dictionary to a class (called Inventory) to work with later. Here's where I'm serializing my JSON:
override func viewDidLoad() {
super.viewDidLoad()
let urlString = "my url to json data";
let session = NSURLSession.sharedSession();
let url = NSURL(string: urlString)!;
session.dataTaskWithURL(url) { (data: NSData?, response:NSURLResponse?, error: NSError?) -> Void in
if let responseData = data {
do {
let json = try NSJSONSerialization.JSONObjectWithData(responseData, options: NSJSONReadingOptions.AllowFragments)
print(json) //this prints out the above formatted json
if let dict = json as? Dictionary<String, AnyObject> {
print(dict["inventory"]![0]!["description"]);
print(dict["inventory"]![0]!["item"]);
print(dict["inventory"]![0]!["quantityOnHand"]);
}
} catch {
print("Could not serialize");
}
}
}.resume()
}
I'm able to print out each value using something like print(dict["inventory"]![0]!["description"]); but that seems inefficient.
Do I need a for loop counting the number of dictionaries? Or a for (key, value) loop? The fact that it's a bunch of dictionaries inside of an array named inventory is really throwing me off. If it were JSON returning key:value pairs in a single dictionary I think I could figure it out on my own. I'm sort of stuck on what to do after putting my json["inventory"] into a variable.
First of all cast the JSON serialization to something meaningful,
in this case Dictionary<String, AnyObject>
let json = try NSJSONSerialization.JSONObjectWithData(responseData, options: NSJSONReadingOptions.AllowFragments) as! Dictionary<String, AnyObject>
Then retrieve the array of dictionaries, the JSON string reveals that it contains only String types.
let inventoryArray = dict["inventory"] as! [Dictionary<String, String>]
if inventory is optional, use optional bindings
if let inventoryArray = dict["inventory"] as? [Dictionary<String, String>] { }
Now you can get the items in the array with a simple loop, any type casting is not needed.
for anItem in inventoryArray {
print("description:", anItem["description"])
print("item: ", anItem["item"])
print("quantityOnHand: ", anItem["quantityOnHand"])
}

iOS SWIFT - JSON object nil after NSJSONSerialization

hello I am trying to read JSON as an array from the server not the dictionary. If I do this
let json: NSArray?
do {
json = try NSJSONSerialization.JSONObjectWithData(data!, options: .AllowFragments) as! NSArray
print("json is \(json)")
}
json object comes nil through this code and also I can't access the variable like this json["code"] I have tried this too
NSJSONSerialization.JSONObjectWithData(data!, options: .MutableLeaves) as! NSArray
But If I don't specify any type and let the variable as AnyObject
do {
let json = try NSJSONSerialization.JSONObjectWithData(data!, options: .AllowFragments)
print("json is \(json["code"]!)")
}
It works But 1st problem here is it prints Optional in the debugger but its least of my worries compared to that I can't do something like this
if json["code"] == 200 {
}
If I do this it says
Binary operator '==' cannot by applied to operands of type Anyobject? and Int
what I want is to get the data in NSArray. I don't want the json variable to be set as AnyObject. Inshort I want this code to work
let json: NSArray?
do {
json = try NSJSONSerialization.JSONObjectWithData(data!, options: .AllowFragments) as! NSArray
print("json is \(json)")
}
if its possible. I don't know what I am doing wrong here
json:
{"code":200,"msg":"login success"}
If printing json["code"] works, then json is doubtless a dictionary.
JSONObjectWithData returns AnyObject that is
"I-have-no-idea-what-it-is-but-it-is-some-kind-of-object-and-not-a-value" (thanks to gnasher729 for the more accurate paraphrase of AnyObject)
Since you know the object is [String:AnyObject] cast the type
let json = try NSJSONSerialization.JSONObjectWithData(data!, options: .AllowFragments) as! [String:AnyObject]
Then get the code – which is an Int – with
if json["code"] as! Int == 200 {
}
or with optional binding if the key is optional
if let code = json["code"] as? Int {
if code == 200 {
}
}

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
}

Cannot convert JSON to the correct format

I'd like to use JSON output from the public Web Service https://api.rbp-zp.cz/1.3/services/district/ but looks like there is a problem with encoding in this case.
AFNetworking use to do conversion in such cases (by specific respondSerializer) like this:
var op = AFHTTPRequestOperation (request: request)
op.responseSerializer = AFJSONResponseSerializer()
but it fails because of the invalid JSON structure.
I have tried to do conversion myself, but no outcome
let rObject: AnyObject? = NSJSONSerialization.JSONObjectWithData(decodedData, options:.AllowFragments, error: nil)
When I put manually this JSON from browser to validator http://jsonlint.com, then it says it is in incorrect format.
Strangely enough when I put the JSON message from my log into the validator then the structure is valid.
Any help would be appreciated.
func convertStringToDictionary(text: String) -> [String:String]? {
if let data = text.dataUsingEncoding(NSUTF8StringEncoding) {
var error: NSError?
let json = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.allZeros, error: &error) as? [String:String]
if error != nil {
println(error)
}
return json
}
return nil
}
let str = "{\"name\":\"James\"}"
let result = convertStringToDictionary(str) // ["name": "James"]
if let name = result?["name"] { // The `?` is here because our `convertStringToDictionary` function returns an Optional
println(name) // "James"
}
In your version, you didn't pass the proper parameters to NSJSONSerialization and forgot to cast the result. Also, it's better to check for the possible error. Last note: this works only if your value is a String. If it could be another type, it would be better to declare the dictionary conversion like this:
let json = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.allZeros, error: &error) as? [String:AnyObject]
and of course you would also need to change the return type of the function:
func convertStringToDictionary(text: String) -> [String:AnyObject]? { ... }
Ok, so workaround is trimming those funny characters in the end,..don't like it much but works
let range:NSRange = NSMakeRange(0, res.length - 3);
let refinedData:NSData = res.subdataWithRange(range)
let resObject = NSJSONSerialization.JSONObjectWithData(refinedData, options:NSJSONReadingOptions.allZeros, error: &error) as! NSArray
resObject is correctly filled as NSArray now

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