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).
I am parsing and NSString value but getting null in console. Please help me with the issue.
NSString *responseData = [[NSString alloc] initWithData:_responseData encoding:NSASCIIStringEncoding];
NSLog(#"Data: %#", responseData);
NSData *data = [responseData dataUsingEncoding:NSUTF8StringEncoding];
id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSDictionary *res = [json objectForKey:#"demo"];
NSLog(#"res is %#",res);
I was having a similar problem in one of my projects. I was trying to create NSString from NSData(response from webservice) and i was getting a nil. I found out that using NSASCIIStringEncoding when creating the String solved my problem. It turns out that even though UTF8 has all ASCII chars, char * may not line up correctly for certain characters and by default the init methods do nonlossy encoding which means that nil gets returned when an unexpected char is encountered.
For your case this could be your code.
NSString *responseData = [[NSString alloc] initWithData:_responseData encoding:NSASCIIStringEncoding];
NSLog(#"Data: %#", responseData);
NSData *data = [responseData dataUsingEncoding:NSASCIIStringEncoding];
id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSDictionary *res = [json objectForKey:#"demo"];
NSLog(#"res is %#",res);
NOTE: I am not sure why you are doing all the _responseData->data conversion. If you are doing that just to deserialize your _responseData to json object, you could use it directly in NSJSONSerialization. As below.
id json = [NSJSONSerialization JSONObjectWithData:_responseData options:0 error:nil];
For more information check out this link.
Maybe error appear because you using different encoding? Try using NSUTF8StringEncoding in NSString and in NSData.
From NSString class reference:
-initWithData:encoding:
Return Value
An NSString object initialized by converting the bytes in data into Unicode characters using encoding. The returned
object may be different from the original receiver. Returns nil if the
initialization fails for some reason (for example if data does not
represent valid data for encoding).
Where are you getting _responseData from? Is it definitely an NSDataobject?
Are you sure that you are using the correct encoding?
Could you print out _responseData and update your question so we can take a look?
I just try to deploy client server apps in Objective-C. I get an json string like this from server when I make a query:
#"{"url":"http://my-company.com/json"}".
How do I extract the http://my-company.com/json directly using Objective C?
Read more about NSJSONSerialization
NSString *jsonString = #"{\"url\":\"http://my-company.com/json\"}";
NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSError *e;
NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&e];
NSString *url = [jsonDict objectForKey:#"url"];
NSLog(#"url: %#", url);
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 = ç
My json response from a URL is:
[
{"status":0,
"id":"26",
"content":"See info field for info",
"time":1347565292761,
"info": {"id":"26",
"name":"Ruti",
"twitterPageFollowers":null,
"facebookPageLikes":null,
"activeEmailClients":1}
}
]
I need to extract from it the following strings:
twitterPageFollowers
facebookPageLikes
activeEmailClients
How can I do it?
I tried parsing like this
NSData *urlData=[NSURLConnection sendSynchronousRequest:serviceRequest returningResponse:nil error:nil ];
NSString *returnString=[[NSString alloc]initWithData:urlData encoding:NSUTF8StringEncoding];
NSData *jsonData = [returnString dataUsingEncoding:NSUTF8StringEncoding];
NSArray *json = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:nil];
NSDictionary *response = [json objectAtIndex:0];
NSString *info = [response objectForKey:#"info"];
NSData *businessInfoString = [info dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *businessInfo =
[NSJSONSerialization JSONObjectWithData: businessInfoString
options: NSJSONReadingMutableContainers
error: nil];
And the return data is ok, but I get [__NSCFDictionary dataUsingEncoding:unrecognized selector sent to instance for the last NSDictionary creation from info field.
What is wrong or what is the shorter way to retrieve the above fields?
When you retrieve the "info" field using [response objectForKey:#"info"];, you already get an NSDictionary! (and NOT an NSString).
That's why when you try to call dataUsingEncoding: on this object (that you believed was an NSString but is as NSDictionary) you get the exception.
There is no need to retrieve the value of "info" key then converting it to NSData and converting it back a JSONObject, because it is already a JSONObject, namely an NSDictionary in your case. Why bother trying to convert it back and forth, whereas [response objectForKey:#"info"]; already returns that businessInfo dictionary that you expect at the end of your code?