Error with parsing JSON with NSJSONSerialization - objective-c

I use openweathermap API to print current weather. I need to parse this JSON (JSON with available cities). I tried to parse it with NSJSONSerializer, but the answer was :"error NSError * domain: #"NSCocoaErrorDomain" - code: 3840".
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"city.list" ofType:#"json"];
NSString *myJSON = [[NSString alloc] initWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
NSError *error;
NSData *objectData = [myJSON dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:objectData options:NSJSONReadingMutableContainers error:&error];
As i understand, error 3840 says about wrong JSON format, but i have downloaded JSON from official openweathermap page. What's wrong? How parse this JSON correctly?

The file is no valid JSON, but a list of valid JSONs.
{"_id":707860,"name":"Hurzuf","country":"UA","coord":{"lon":34.283333,"lat":44.549999}}
{"_id":519188,"name":"Novinki","country":"RU","coord":{"lon":37.666668,"lat":55.683334}}
{"_id":1283378,"name":"Gorkhā","country":"NP","coord":{"lon":84.633331,"lat":28}}
…
Such a list in a valid JSON would look like this …:
[
{"_id":707860,"name":"Hurzuf","country":"UA","coord":{"lon":34.283333,"lat":44.549999}},
{"_id":519188,"name":"Novinki","country":"RU","coord":{"lon":37.666668,"lat":55.683334}},
{"_id":1283378,"name":"Gorkhā","country":"NP","coord":{"lon":84.633331,"lat":28}},
…
]
… or like this …
{
{"707860": {"name":"Hurzuf","country":"UA","coord":{"lon":34.283333,"lat":44.549999}},
{"519188": {"name":"Novinki","country":"RU","coord":{"lon":37.666668,"lat":55.683334}},
{"1283378":{"name":"Gorkhā","country":"NP","coord":{"lon":84.633331,"lat":28}},
…
However, what you can do is to iterate over the list and convert it item separately:
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"city.list" ofType:#"json"];
NSString *myList = [[NSString alloc] initWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
// Separate the lines
NSArray *myItems = [myList componentsSeperatedByCharactersInSet:[NSCharacterSet newLineCharacterSet];
NSError *error;
for( NSString *JSON in myItems )
{
if( [JSON length]==0)
{
// empty line
continue;
}
NSData *objectData = [JSON dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *object = [NSJSONSerialization JSONObjectWithData:objectData options:NSJSONReadingMutableContainers error:&error];
if( object == nil )
{
NSLog( #"Error %# reading\n%#", error, JSON);
}
}

Your json is not formatted correctly.
{"_id":707860,"name":"Hurzuf","country":"UA","coord":{"lon":34.283333,"lat":44.549999}}
{"_id":519188,"name":"Novinki","country":"RU","coord":{"lon":37.666668,"lat":55.683334}}
should be
[{"_id":707860,"name":"Hurzuf","country":"UA","coord":{"lon":34.283333,"lat":44.549999}},
{"_id":519188,"name":"Novinki","country":"RU","coord":{"lon":37.666668,"lat":55.683334}},
...]
Note the encapsulating square brackets and commas at the end.
Or you could parse the text line-by-line (it seems it is ment to be parsed like that).

Related

reading JSON, null

Here's my JSON
{
"name": "abe",
}
and this is a part of my code
self.fileRoot = [[NSBundle bundleForClass:[self class]] pathForResource:#"name" ofType:#"json"];
self.jsonString = [NSString stringWithContentsOfFile:self.fileRoot encoding:NSUTF8StringEncoding error:nil];
self.jsonParser = [[SBJsonParser alloc] init];
self.dict = [self.jsonParser objectWithString:self.jsonString];
NSLog(#"\njsonString: %#\njsonParser: %#\ndict: %#\n", self.jsonString, self.jsonParser, self.dict);
the log is:
jsonString: {
"name": "abe",
}
jsonParser: <SBJsonParser: 0x8d6b7f0>
dict: (null)
I have the problem that's why dict said "(null)"
I'm pretty sure this code used to work when I tested it last time(about 3 months ago)
Any suggestion? Thank you in advance.
Remove the comma from the key value pair, since you just have a single name-value pair in json string
//convert string to NSData
NSString* str = #"{'name':'abe'}";
NSData* data = [str dataUsingEncoding:NSUTF8StringEncoding];
//create dictionary
NSError *error = nil;
NSDictionary *dict = [NSJSONSerialization
JSONObjectWithData: data
options:0
error:&error];
NSLog(#"Name: %#", dict[#"name"]);

App crashing because NSArray objectforkey: Objective C

I am trying to parse some Json with Objective C.
My problem is that I am getting the correct json back but when I try parse some of the json my app crashes.
// i will use a code from connect to DB tutorial
NSString *strURL = [NSString stringWithFormat:#"http://www.ddproam.co.za/Central/Asset/AssetsWithSerial?Serial=S00000001"];
// to execute php code
NSData *dataURL = [NSData dataWithContentsOfURL:[NSURL URLWithString:strURL]];
// to receive the returend value
NSString *strResult = [[NSString alloc] initWithData:dataURL encoding:NSUTF8StringEncoding];
NSLog(#"Login response:%#",strResult);
NSError *error;
//parse out the json data
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:dataURL //1
options:kNilOptions
error:&error];
NSArray* defineJsonData = [json objectForKey:#"AssetDesc"]; //2
NSLog(#"value: %#", defineJsonData); //3
Here is my json:
[{"AssetID":1,"AssetName":"Asset 1","AssetDesc":"This is a manually inserted Asset","AssetTypeID":1,"AssetTypeDesc":"This is a manually inserted Asset Type"}]
I am trying to get the AssestName out of the string. I must be doing something wrong.
The whole thing is an array containing a dictionary, not a dictionary containing an array...
This is a very dirty way to get the value you want - you want to write something more safe than this. Try checking the type of class returned before you try to use it...
NSArray* json = [NSJSONSerialization JSONObjectWithData:dataURL //1
options:kNilOptions
error:&error];
NSDictionary* defineJsonData = [json lastObject]; //2
NSLog(#"value: %#", [defineJsonData objectForKey:#"AssetDesc"]); //3

NSJSONSerialization: treating special characters properly

I want to use online data from a JSON file. It's currently working, but when I use special characters it shows "null". Here's the code I'm using:
NSString *urlString = [NSString stringWithFormat:#"http://belesios.com/burc/koc2.php"];
NSURL *url = [NSURL URLWithString:urlString];
NSData *data = [NSData dataWithContentsOfURL:url];
NSError *error;
NSMutableDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
NSLog(#"%#", json);
NSString *ciktiText = [[NSString alloc] initWithFormat:#"%#", json];
[kocLabel setText:ciktiText];
For example, if my file contains ç or ü, null is returned. What do I need to do?
Try this method to find out what encoding is used when data is pulled from server:
NSStringEncoding encoding;
NSString *jsonString =[NSString stringWithContentsOfURL:URL usedEncoding:&encoding error:&error];
if (error)
NSLog(#"Error: %#", error);
You should check encoding of data returned by the server. Your code is correct but you should add some check if error != nil then don't execute and display or log that.
NSString *jsonString = #"{\"abc\":\"ç or ü\"}";
NSDictionary *jsonObj = [NSJSONSerialization JSONObjectWithData:[jsonString dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingAllowFragments error:&error];
NSLog(#"Output: %#", jsonObj);
Output: { abc = "\U00e7 or \U00fc"; } This is how your server response should look like with encoded char if you use Fiddler or some other software to print raw response.
Currently your data looks like where as UTF8 encoded chars should be like \U00e7 = ç

Parsing special characters in JSON

I'm now parsing with NSJSONSerialization
NSData *jsonData = [NSData dataWithContentsOfURL:[NSURL URLWithString:#"url"]];
NSError *jsonError = nil;
id jsonObject = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&jsonError];
NSDictionary *jsonDictionary = (NSDictionary *)jsonObject;
[self setTableData:jsonDictionary];
But it won't parse my JSON because of special characters in the JSON like the letter 'ü' when i remove the 'ü' from the JSON it's working correclty. I tried the code above and:
options:utf8...
Does anyone know how i can fix this?
Try using NSString with which you can explicitly specify encoding. Ex:
NSString *string = [NSString stringWithContentsOfURL:webURL encoding:NSUTF8StringEncoding error:&error];
You can then convert the NSString object to NSData and then do the JSON serialisation..
Try to change NSJSONReadingMutableContainers with NSJSONReadingMutableLeaves. This solved me similar problem.

Decode JSON to NSArray or NSDictionary

I hope to decode the JSON data below:
{
"content":
[
{
"1":"a",
"2":"b",
"3":"c",
"4":"d",
"mark":"yes"
}
]
}
Not sure if put it in NSArray or NSDictionary
Welcome any comment
which iOS version are you using? in iOS 5 you have the NSJSONSerialization class to parse JSON data, if you need to target older iOSs or MAC OSX you should use third parties lib such as SBJSON. The string posted will be a NSDictionary with an array with one dictionary. The array will be accessible using the key #"content"
In code:
NSString * jsonString = #"blblblblblb";
NSStringEncoding encoding;
NSData * jsonData = [jsonString dataUsingEncoding:encoding];
NSError * error=nil;
NSDictionary * parsedData = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:&error];
In SWIFT 2.0:
let jsonString = "blblblblblb"
let encoding = NSUTF8StringEncoding
let jsonData = jsonString.dataUsingEncoding(encoding)
guard let jData = jsonData else {return}
do {
let parsedData = try NSJSONSerialization.JSONObjectWithData(jData, options: [])
} catch let error {
print("json error: \(error)")
}
[UPDATE]
The NSJSONSerialization class is also available for 10.7 my comment wasn't correct.
That particular string will decode into an NSDictionary because the outermost thing is a JSON object which maps onto a NSDictionary for every JSON implementation I have ever seen. If you want to process an arbitrary string, you'll need to test what you get back
NSError *jsonError;
id parsedThing = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];
if (parsedThing == nil)
{
// error
}
else if ([parsedThing isKindOfClass: [NSArray class]])
{
// handle array, parsedThing can be cast as an NSArray safely
}
else
{
// handle dictionary, parsedThing can be cast as an NSDictionary
// NB only dictionaries and arrays allowed as long as NSJSONReadingAllowFragments
// not specified in the options
}
stringWithContentsOfFile:encoding: is deprecated in iOS<6
for iOS 6+
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"contents" ofType:#"json"];
NSError * error=nil;
NSString *jsonString = [NSString stringWithContentsOfFile:filePath encoding:nil error:&error];
NSData * jsonData = [jsonString dataUsingEncoding:nil];
NSArray * parsedData = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:&error];
contents.json file is in your bundle.
You can do the following:
NSData *data = ...; //JSON data
NSError *jsonError = nil;
[NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];
You will get back an NSDictionary containing an NSArray containing a single NSDictionary containing five NSString objects.
I used google speech recognition API and I was getting a json response which was not directly parsable on iOS. Results samples were like :
First I tried saying Hello 1 2 3 which was recognised without issues. Json response was :
{"result":[]}
{"result":[{"alternative":[{"transcript":"hello 123","confidence":0.59780568},{"transcript":"hello 1 2 3"}],"final":true}],"result_index":0}
Or when talked for too long, I got a 404 HTML like below :
<html><title>Error 400 (Bad Request)!!1</title></html>
And when I spoke gibberish , I got :
{"result":[]}
So to parse all such response, I used the below code :
NSString *msg = #"Could not synthesize !";
NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"responseString: %#",responseString);
if([responseString containsString:#"transcript"]&&responseString.length>25)
{
responseString = [responseString stringByReplacingOccurrencesOfString:#"{\"result\":[]}" withString:#""];
NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:[responseString dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:nil];
if(dictionary!=nil)
if(dictionary.allValues.count>0)
{
NSArray *array =[dictionary valueForKeyPath:#"result.alternative.transcript"];
if(array)
{
NSArray *array2 = [array objectAtIndex:0];
if(array2)
{
NSLog(#"%#",[array2 objectAtIndex:0] );
msg = [array2 objectAtIndex:0];
};
}
}
}
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"Google Response" message:msg delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
Hope this helps someone.