NSdictionary is not Null, but showing 0 key/value - iphone

I am fetching data from server using json. It is checked url is getting hit response is received, printed in console all values fetched from json. But dictionary and tried with array also both are showing null values by breakpoints but when printed in console showing data is fetched. Below is the code.
NSString *urlStr = [NSString stringWithFormat:#"http://server39.pivbfg.com/360ads/apps/ads/%#/android/1360/ord0.9109502528132325?json=1&package_url=%#",self.mStrPid, base64String];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:
[NSURL URLWithString:
[urlStr stringByAddingPercentEscapesUsingEncoding:
NSUTF8StringEncoding]]];
NSLog(#"req-------------%#",request);
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSString *json_string = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
NSDictionary *json_dict = [json_string JSONValue];
NSLog(#"json_dict\n%#",json_dict);
NSLog(#"json_string\n%#",json_string);
NSMutableArray *arrAds = [[NSMutableArray alloc]init];
arrAds = [json_dict valueForKey:#"ads"];
request is going ok.
json_string is ok.
But json_dict printing values in console but showing null at breakpoints. What could be the reason for this. One thing is i am using ARC, does it affect this code. Please guide for the above.
This is the error: * Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<__NSCFString 0x9851e00> valueForUndefinedKey:]: this class is not key value coding-compliant for the key ads.'* First throw call stack:
(0xb5012 0x13a9e7e 0x13dfb1 0xe565ed 0xdc28db 0xdc288d 0x613d 0x3d1707 0x3d1772 0x320915 0x320caf 0x320e45 0x329e57 0x5942 0x2ed697 0x2edc87 0x2eee8b 0x3001f5 0x30112b 0x2f2bd8 0x2202df9 0x2202ad0 0x2abf5 0x2a962 0x5bbb6 0x5af44 0x5ae1b 0x2ee6ba 0x2f053c 0x544d 0x2b65 0x1)
libc++abi.dylib: terminate called throwing an exception
Edited code
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSString *json_string = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
NSError *error;
NSData *jsonData = [json_string dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *results = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
NSLog(#"results\n%#",results);
NSMutableArray *arrAds = [[NSMutableArray alloc]init];
arrAds = [results valueForKey:#"ads"];
NSLog(#"dict-------------%#",arrAds);
Now the same problem is coming with the array arrAds. It is printing values in console but empty.

Well the error tells you that the property you are retrieving from the JSON is not a dictionary but a string. It looks like you json_string does not contain a valid JSON object.
In your example you'r also leaking:
NSMutableArray *arrAds = [[NSMutableArray alloc]init];
arrAds = [json_dict valueForKey:#"ads"];
You create a new NSMutableArray only to assing a new object to the same variable the next line. Also the object returned will not a none mutable version. You can just replace it with:
NSMutableArray *arrAds = [[json_dict objectForKey:#"ads"] mutableCopy];

Related

How to separate JSON response in iphone

I have an application in which I am having a json response like this.
{"success":"true","message":"You have logged in","pserial":"1"} and I am separating with ":".
And I am getting data like this pSerial:"1"} but I want only 1 value.
NSURL *url = [NSURL URLWithString:strUrl];
NSData *respData = [NSData dataWithContentsOfURL:url];
NSString *strResp = [[NSString alloc]initWithData:respData encoding:NSUTF8StringEncoding];
NSString *approvalString = [[strResp componentsSeparatedByString:#":"] objectAtIndex:3];
NSLog(#"pSerial:%#",approvalString);
for Example :
SBJsonParser *jsonPar = [[SBJsonParser alloc] init];
NSError *error = nil;
NSArray *jsonObj = [jsonPar objectWithString:jsonString error:&error];
id jsonObj = [jsonPar objectWithString:jsonString error:&error];
if ([jsonObj isKindOfClass:[NSDictionary class]])
// treat as a dictionary, or reassign to a dictionary ivar
else if ([jsonObj isKindOfClass:[NSArray class]])
// treat as an array or reassign to an array ivar.
Then get the value :
NSMutableArrary *userMutArr = [NSMutableArray array];
for (NSDictionary *dict in jsonObj)
{
User *userObj = [[[User alloc] init] autorelease];
[userObj setFirstName:[dict objectForKey:#"firstName"]];
[userObj setLastName:[dict objectForKey:#"lastName"]];
[userObj setAge:[[dict objectForKey:#"age"] intValue]];
[userObj setAddress:[dict objectForKey:#"address"]];
[userObj setPhoneNumbers:[dict objectForKey:#"phoneNumber"]];
[userMutArr addObject:userObj];
}
Hope you will understand. and read some Documents. it will help you.
It looks like you are in need of JSON Parsing. Here, what you want is JSON Parsing, not separating data from the JSON Response. JSON is the format of the data in which data is formatted in Key-Value pairs. You can fetch the "Value" of any object using the "Key".
Your first two lines are correct.
NSURL *url = [NSURL URLWithString:strUrl];
NSData *respData = [NSData dataWithContentsOfURL:url];
Now, you can parse JSON Response like this :
NSError* error;
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:respData options:kNilOptions error:&error];
NSString *pSerial = [json objectForKey:#"pserial"];
This will give you the value of "pserial" from your response. Similarly, you can get the values for "success" and "message". You can check it using this line :
NSLog(#"pserial :: %#",pserial);
You need to parse the JSON Response String, you can use any JSON parser like:
https://github.com/stig/json-framework/
And in your code do:
NSString *strResp = [[NSString alloc]initWithData:respData encoding:NSUTF8StringEncoding];
NSDictionary *ResponseDictionary = [strResp JSONValue];
NSString * pSerial = (NSString*)[ResponseDictionary objectForKey:#"pserial"];
Dont separation by ":" just use JSONValue your response is like
// {"success":"true","message":"You have logged in","pserial":"1"}
// with SBJsonParser parse your object like this
NSDictionary *responseJson = [YOUR-OBJECT JSONValue];
Note: dont forget to add Json header file
Its better you use any OpenSource Json Parser
Here is a stack post Comparison of different Json Parser for iOS

How to parse json data with "var abcd =" header

I'm having problem with parsing json data file on iOS.
This is a sample from the data.json file:
var devs = [
{
"ident":"1",
"firstname":"Jan",
"lastname":"Kowalski",
"img":"http://www.placekitten.com/125/125",
"tech":"iOS, HTML5, CSS, RWD",
"github":"placeholder",
"opensource":"1",
"twitter":"placeholder"
},
{
"ident":"2",
"firstname":"WacĹaw",
"lastname":"GÄsior",
"img":"http://www.placekitten.com/124/125",
"tech":"Android, Java, Node.js",
"github":"GÄsiorBKR",
"twitter":"wacek5565"
},
and so on.
With "normal" json files I use:
NSURLResponse *response;
NSError *myError;
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://somerailsapplication/posts.json"] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:30.0f];
NSData *data = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:&response error:&myError];
NSDictionary *res = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:&myError];
Unfortunately this solution doesn't work in this case.
Is there any chance to get this working without searching for specific string "var dev=[" and the last "]" in the downloaded data?
The response is javascript, not JSON, so you won't be able to use a JSON parser directly. If you can't change the server output, the easiest thing would be to strip the beginning and end of the data, as you suggested. You could also embed the response in an HTML template and evaluate it in a webview, but that seems like a lot of more work.
Starting at the point where you've got the data:
NSData *data = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:&response error:&myError];
NSMutableString *dataAsString = [[NSMutableString alloc] initWithData:data encoding:NSUTF8StringEncoding];
[dataAsString deleteCharactersInRange:NSMakeRange(0, 11)];
data = [dataAsString dataUsingEncoding:NSUTF8StringEncoding];
NSArray *res = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:&myError];
This turns the data into a string, removes the first 11 characters, turns it back into data, and then parses it as normal. (I've changed it to NSArray since your data is in an array)

CHCSVParser - how to load from webserver

I would like to parse csv from webserver which gets updated everyday.I am using the csvparser from this link https://github.com/davedelong/CHCSVParser and I am using this code:
NSError *err = [[[NSError alloc] init] autorelease];
NSString *lunchFileURL = [[NSString stringWithFormat:#"http://www.somewhere.com/LunchSpecials.csv"] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *lunchFile = [NSString stringWithContentsOfURL:[NSURL URLWithString:lunchFileURL] encoding:NSUTF8StringEncoding error:&err];
CHCSVParser *p = [[CHCSVParser alloc] initWithContentsOfCSVString:lunchFile usedEncoding:&encoding error:nil];
I get this error :
No visible #interface for 'CHCSVParser' declares the selector 'initWithContentsOfCSVString:usedEncoding:error:'
I checked this link Load remote csv into CHCSVParser and its not working .I am a noob to ios ,Please let me know how to fix this .Really Appreciate the help.Thanks in Advance.
It should probably be:
NSError *err;
NSString *lunchFileURL = [[NSString stringWithFormat:#"http://www.somewhere.com/LunchSpecials.csv"] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *lunchFile = [NSString stringWithContentsOfURL:[NSURL URLWithString:lunchFileURL]
encoding:NSUTF8StringEncoding
error:&err];
// if you're going to create a CHCSVParser yourself, the syntax is:
CHCSVParser *p = [[CHCSVParser alloc] initWithCSVString:lunchFile
encoding:NSUTF8StringEncoding
error:&err];
// or, if you're going to use NSArray+CHCSVAdditions.h, the syntax might be:
NSArray *array = [[NSArray alloc] initWithContentsOfCSVString:lunchFile
encoding:NSUTF8StringEncoding
error:&err];
Note:
You don't need to alloc/init the NSError object; these classes that take a NSError ** parameter will create the autorelease error object for you if they encounter an error; otherwise they leave it alone;
The CHCSVParser class method is not initWithContentsOfCSVString, but rather initWithCSVString;
Alternatively, if you use the NSArray class extension, then the syntax is arrayWithContentsOfCSVString or initWithContentsOfCSVString; and
You specified an encoding of &encoding, but this parameter is not a pointer, so I don't see how that can possibly be right; I've just specified the encoding.
I assume you want to use the NSArray+CHCSVAdditions category method initWithContentsOfCSVString or arrayWithContentsOfCSVString (which gives you an autorelease object), not the CHCSVParser, but it's up to you.

EXC_BAD_ACCESS whilst parsing JSON using SBJSON. Corresponding message states variable json_string is not a CFString

I have the following response from server side:
{"_playLists":[{"name":"Playlist 1","items":[{"name":"Poza 1","target":"http:\/\/myaudi.fr","url":"http:\/\/test.res-novae.fr\/sfrplay\/upload\/image\/pic1_iphone3.jpg","url_thumb":"http:\/\/test.res-novae.fr\/sfrplay\/upload\/thumb\/pic1_iphone3_thumb.jpg"},{"name":"Poza 2","target":"http:\/\/audifrance.fr","url":"http:\/\/test.res-novae.fr\/sfrplay\/upload\/image\/pic2_iphone3.jpg","url_thumb":"http:\/\/test.res-novae.fr\/sfrplay\/upload\/thumb\/pic2_iphone3_thumb.jpg"}]},{"name":"Playlist 2","items":[{"name":"Poza 3","target":"http:\/\/google.ro","url":null,"url_thumb":null}]}]}
And I'm trying to acces this by using:
SBJSON *parser = [[SBJSON alloc] init];
NSString *responseString = [request responseString];
NSString *json_string = [[NSString alloc] initWithData:responseString encoding:NSUTF8StringEncoding];
NSArray *statuses = [parser objectWithString:json_string error:nil];
But I get EXC_BAD_ACCESS at this line
NSString *json_string = [[NSString alloc] initWithData:responseString encoding:NSUTF8StringEncoding];
saying variable json_string is not a CFString.
Can someone help me solve this and tell me how to act further to acces the JSON components?Thank you:)
EDIT:
{
items = (
{
name = "Poza 1";
target = "http://myaudi.fr";
url = "http://test.res-novae.fr/sfrplay/upload/image/pic1_iphone3.jpg";
"url_thumb" = "http://test.res-novae.fr/sfrplay/upload/thumb/pic1_iphone3_thumb.jpg";
},
{
name = "Poza 2";
target = "http://audifrance.fr";
url = "http://test.res-novae.fr/sfrplay/upload/image/pic2_iphone3.jpg";
"url_thumb" = "http://test.res-novae.fr/sfrplay/upload/thumb/pic2_iphone3_thumb.jpg";
}
);
name = "Playlist 1";
},
{
items = (
{
name = "Poza 3";
target = "http://google.ro";
url = "<null>";
"url_thumb" = "<null>";
}
);
name = "Playlist 2";
}
You should use one of the JSON frameworks available out there, i.e. JSONKit or json-framework, which both makes it really easy to convert strings to JSON objects (i.e. an NSDictionary).
If you're using json-framework, you'd only have to do the following (if you've included JSON.h):
NSDictionary *jsonObject = [responseString JSONValue];
There is a issue with your line
NSString *json_string = [[NSString alloc] initWithData:responseString encoding:NSUTF8StringEncoding];
you have declared responseString as NSString *responseString = [request responseString];
and you are giving it as Data while allocating json_string
You do not need this line
NSString *json_string = [[NSString alloc] initWithData:responseString encoding:NSUTF8StringEncoding];
responseString is already a string (and initWithData: expects a NSData object not NSString). Just feed it straight to the parser:
NSArray *statuses = [parser objectWithString:responseString error:nil];
Can someone help me solve this and tell me how to act further to acces
the JSON components?
You now have a nice NSArray of NSDictionary objects representing your JSON data, you can access the first item, represented by
{"name":"Playlist 1","items":[{"name":"Poza 1","target":"http:\/\/myaudi.fr","url":"http:\/\/test.res-novae.fr\/sfrplay\/upload\/image\/pic1_iphone3.jpg","url_thumb":"http:\/\/test.res-novae.fr\/sfrplay\/upload\/thumb\/pic1_iphone3_thumb.jpg"},{"name":"Poza 2","target":"http:\/\/audifrance.fr","url":"http:\/\/test.res-novae.fr\/sfrplay\/upload\/image\/pic2_iphone3.jpg","url_thumb":"http:\/\/test.res-novae.fr\/sfrplay\/upload\/thumb\/pic2_iphone3_thumb.jpg"}]}
by getting the first element in the array
NSDictionary* dict = [statuses objectAtIndex:0];
and the keys in the dictionary should be "name", and "items". The object for "name" will be an NSString and the object for "items" will be an NSArray containing further NSDictionary objects describing each item.

Cast JSON object (NSCFDictionary) to string and parse it

I'm working with facebook connect and trying to handle the JSON object that i'm receiving.
I invoked the requstWithGraphPath method and need to get back a JSON object,
tried to parse it and getting an error:
SBJSON *parser = [[SBJSON new] autorelease];
NSData *data = [[NSData alloc] initWithData:result];
NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; -> in this line - "[__NSCFDictionary length]: unrecognized selector sent to instance"
NSArray *events = [parser objectWithString:jsonString];
What's the problem?
Can I get the string in an other way or parse the object differently?
Thanks.
If you are working with the delegate callback
- (void)request:(FBRequest *)request didLoad:(id)result;
the parsing work has been done for you. Traverse the NSDictionary or NSArray to find the data you are looking for. If you are working with the delegate callback
- (void)request:(FBRequest *)request didLoadRawResponse:(NSData *)data;
you should initialize an NSString with the data, and use the category method that SBJSON adds to NSString for creating an id. That is assuming the data is data that constructs a string.
NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
id result = [jsonString JSONValue];
Are you sure the error happens on that line, or does it happen on the line above?
If result is an NSDictionary (or CFDictionary, same thing), then it is already parsed and you do not need to do that yourself — and it could cause that error message too, on the line above.
The line:
data = [[NSData alloc] initWithData:result];
is almost certainly not what you want to do, as it is equivalent to
data = [result copy];
assuming that result is an NSData object (or NSMutableData), which I'm guessing it isn't.