Update: I just tested my JSON format returned from the server using JSONlint and it is fine.
I'm getting an exception with NSJSONSerialization in an AFNetworking call to a php script that returns JSON data. I've looked at the other questions here with the same issue and tried those solutions but am still getting the error.
It crashes on this line:
NSError *e = nil;
NSMutableArray *jsonArray =
[NSJSONSerialization JSONObjectWithData: jsonData
options: NSJSONReadingMutableContainers
error: &e];
Error Log:
2012-03-19 18:10:41.291 imageUploader[3538:207] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFArray bytes]: unrecognized selector sent to instance 0x6867430'
My JSON data, when I call the php script through the browser looks like this:
[{"user":"binky","path":"binky-0a96f9aab5267c8.jpg","index":"101"},{"user":"binky","path":"binky-9cf844252c28553.jpg","index":"102"},{"user":"binky","path":"binky-d6c749d25d33015.jpg","index":"103"}]
The NSLog of the data looks like this:
(
{
index = 101;
path = "binky-0a96f9aab5267c8.jpg";
user = binky;
},
{
index = 102;
path = "binky-9cf844252c28553.jpg";
user = binky;
},
{
index = 103;
path = "binky-d6c749d25d33015.jpg";
user = binky;
} )
Finally, I do a test to make sure I have valid JSON data:
if ([NSJSONSerialization isValidJSONObject: jsonData]){
NSLog(#"Good JSON \n");
}
So I can't understand where the source of my error is. Little help?
// AFNetworking operation + block
AFJSONRequestOperation *operation =
[AFJSONRequestOperation JSONRequestOperationWithRequest:myRequest
success:^(NSURLRequest *request, NSHTTPURLResponse *response, id jsonData) {
NSLog(#"Success JSON data:\n %# \n", jsonData); //log data
if ([NSJSONSerialization isValidJSONObject: jsonData]){
NSLog(#"Good JSON \n");
}
NSError *e = nil;
NSMutableArray *jsonArray = [NSJSONSerialization JSONObjectWithData: jsonData options: NSJSONReadingMutableContainers error: &e];
if (!jsonArray) {
NSLog(#"Error parsing JSON: %#", e);
} else {
for(NSDictionary *item in jsonArray) {
NSLog(#"Item: %#", item);
}
}
[self.navigationController popToRootViewControllerAnimated:YES];
}
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
NSLog(#"Error: %#", error);
[self.navigationController popToRootViewControllerAnimated:YES];
}];
Aparently JSONObjectWithData expects NSData rather than an array.
id jsonData seems to be an Array representing the content of your json string. Aparently you are expecting an Array anyway.
For some reason you are doing it twice. Instead of
NSMutableArray *jsonArray = [NSJSONSerialization JSONObjectWithData: jsonData options: NSJSONReadingMutableContainers error: &e];
you could simply use
NSMutableArray *jsonArray = [NSMutableArray arrayWithArray:jsonData];
or, if it does not have to be mutable:
NSArray *jsonArray = (NSArray *) jsonData;
However, you should always test whether it is really an array in jsonData. Depending on the structure within the json string it could be an NSDictionary or nil in case of errors.
Related
Here is what I want to parse.
{
"Words": {
"subjugate": "To conquer. ",
"contemplate": "To consider thoughtfully. ",
"comprise": "To consist of. ",
"pollute": "To contaminate. "
}
}
Here is a very stripped and over-simplified way to handle getting response data back from a server in JSON and serializing the JSON to an NSDictionary:
// this is just for example purposes, in this example the code is already running on a background thread so sending it synhcronously is OK, and I've already created the request object
NSError *error = nil;
NSHTTPURLResponse *response = nil;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
// if we don't have response data
if (!responseData) {
// handle that we got no response from the server
}
if (error) {
// handle the request error
}
// serialize the JSON result into a dictionary
NSError *serializationError = nil;
NSDictionary *resultDictionary = [NSJSONSerialization JSONObjectWithData:responseData options:0 &serializationError];
if (serializationError) {
// handle the error turning the data into dictionary
}
NSDictionary *wordsDictionary = resultDictionary[#"words"];
NSString *exampleValue = wordsDictionary[#"subjugate"]; // will be "To conquer." if everything goes to plan
You can parse as bellow
NSData *data = [#"{\"Words\":{\"subjugate\":\"To conquer.\",\"contemplate\":\"To consider thoughtfully.\",\"comprise\":\"To consist of.\",\"pollute\":\"To contaminate.\"}}" dataUsingEncoding:NSUTF8StringEncoding];
NSError *error = nil;
NSMutableDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
if(error)
{
NSLog(#"Error : %#", error);
}
else
{
NSLog(#"%#", json);
}
Update: I just tested my JSON format returned from the server using JSONlint and it is fine.
I'm getting an exception with NSJSONSerialization in an AFNetworking call to a php script that returns JSON data. I've looked at the other questions here with the same issue and tried those solutions but am still getting the error.
It crashes on this line:
NSError *e = nil;
NSMutableArray *jsonArray =
[NSJSONSerialization JSONObjectWithData: jsonData
options: NSJSONReadingMutableContainers
error: &e];
Error Log:
2012-03-19 18:10:41.291 imageUploader[3538:207] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFArray bytes]: unrecognized selector sent to instance 0x6867430'
My JSON data, when I call the php script through the browser looks like this:
[{"user":"binky","path":"binky-0a96f9aab5267c8.jpg","index":"101"},{"user":"binky","path":"binky-9cf844252c28553.jpg","index":"102"},{"user":"binky","path":"binky-d6c749d25d33015.jpg","index":"103"}]
The NSLog of the data looks like this:
(
{
index = 101;
path = "binky-0a96f9aab5267c8.jpg";
user = binky;
},
{
index = 102;
path = "binky-9cf844252c28553.jpg";
user = binky;
},
{
index = 103;
path = "binky-d6c749d25d33015.jpg";
user = binky;
} )
Finally, I do a test to make sure I have valid JSON data:
if ([NSJSONSerialization isValidJSONObject: jsonData]){
NSLog(#"Good JSON \n");
}
So I can't understand where the source of my error is. Little help?
// AFNetworking operation + block
AFJSONRequestOperation *operation =
[AFJSONRequestOperation JSONRequestOperationWithRequest:myRequest
success:^(NSURLRequest *request, NSHTTPURLResponse *response, id jsonData) {
NSLog(#"Success JSON data:\n %# \n", jsonData); //log data
if ([NSJSONSerialization isValidJSONObject: jsonData]){
NSLog(#"Good JSON \n");
}
NSError *e = nil;
NSMutableArray *jsonArray = [NSJSONSerialization JSONObjectWithData: jsonData options: NSJSONReadingMutableContainers error: &e];
if (!jsonArray) {
NSLog(#"Error parsing JSON: %#", e);
} else {
for(NSDictionary *item in jsonArray) {
NSLog(#"Item: %#", item);
}
}
[self.navigationController popToRootViewControllerAnimated:YES];
}
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
NSLog(#"Error: %#", error);
[self.navigationController popToRootViewControllerAnimated:YES];
}];
Aparently JSONObjectWithData expects NSData rather than an array.
id jsonData seems to be an Array representing the content of your json string. Aparently you are expecting an Array anyway.
For some reason you are doing it twice. Instead of
NSMutableArray *jsonArray = [NSJSONSerialization JSONObjectWithData: jsonData options: NSJSONReadingMutableContainers error: &e];
you could simply use
NSMutableArray *jsonArray = [NSMutableArray arrayWithArray:jsonData];
or, if it does not have to be mutable:
NSArray *jsonArray = (NSArray *) jsonData;
However, you should always test whether it is really an array in jsonData. Depending on the structure within the json string it could be an NSDictionary or nil in case of errors.
I have a WebService, which give me the fallowing Json-String back:
"{\"password\" : \"1234\", \"user\" : \"andreas\"}"
I call the webservice and try to parse the returned data like:
[NSURLConnection sendAsynchronousRequest: request
queue: queue
completionHandler: ^(NSURLResponse *response, NSData *data, NSError *error) {
if (error || !data) {
// Handle the error
} else {
// Handle the success
NSError *errorJson = nil;
NSDictionary *responseDict = [NSJSONSerialization JSONObjectWithData: data options: NSJSONReadingMutableContainers error: &errorJson];
NSString *usr = [responseDict objectForKey:#"user"];
}
}
];
But the resulting NSDictionary looks like:
What has the effect, that I cannot get the values - for example user.
Can someone help me, what I am doing wrong? - Thank you.
From the debugger screenshot is seems that the server is (for whatever reason) returning
"nested JSON": responseDict[#"d"] is a string containing JSON data again, so you have to
apply NSJSONSerialization twice:
NSError *errorJson = nil;
NSDictionary *responseDict = [NSJSONSerialization JSONObjectWithData: data options:0 error: &errorJson];
NSData *innerJson = [responseDict[#"d"] dataUsingEncoding:NSUTF8StringEncoding];
NSMutableDictionary *innerObject = [NSJSONSerialization JSONObjectWithData:innerJson options:NSJSONReadingMutableContainers error:&errorJson];
NSString *usr = [innerObject objectForKey:#"user"];
If you have the option, a better solution would be to fix the web service to return
proper JSON data.
I am using AFJSONRequestOperation to request a remote API:
NSURLRequest *request = [NSURLRequest requestWithURL:url];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
//Remove the SVProgressHUD view
[SVProgressHUD dismiss];
//Check for the value returned from the server
NSData *jsonData = [JSON dataUsingEncoding:NSUTF8StringEncoding];//This line cause crash
NSArray *arr = [NSJSONSerialization JSONObjectWithData:jsonData
options:0
error:nil];
loginDic=[[NSDictionary alloc]init];
loginDic=[arr objectAtIndex:0];
NSLog(#"%#",loginDic);
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
NSLog(#"Request Failed with Error: %#", [error.userInfo objectForKey:#"NSLocalizedDescription"]);
}];
[operation start];
[SVProgressHUD showWithStatus:#"Loading"];
However, the app crashes and I am getting this error:
[__NSCFDictionary dataUsingEncoding:]: unrecognized selector sent to instance
Here is an NSLog for the JSON object returned:
Result = (
{
operation = 5;
result = 1;
}
);
Am I missing something, because I think that I am not parsing correctly the JSON object. Please correct me.
It looks like AFJSONRequestOperation is deserializing JSON to a dictionary for you, and then you're trying to do it again. JSON is an NSDictionary but you're calling an NSString method.
Remove all of this code:
NSData *jsonData = [JSON dataUsingEncoding:NSUTF8StringEncoding];//This line cause crash
NSArray *arr = [NSJSONSerialization JSONObjectWithData:jsonData
options:0
error:nil];
loginDic=[[NSDictionary alloc]init];
loginDic=[arr objectAtIndex:0];
And replace it with:
loginDic = [[JSON objectForKey:#"Result"] lastObject];
(That'll work safely without checking array bounds, but assumes that there's only one element in the array.)
The object you get in the success block is already parsed by AFJSONRequestOperation.
In your case you get a NSDictionary object.
You can check the class of the object using the isKindofClass-method:
if ([JSON isKindOfClass:[NSDictionary class]]) {
NSDictionary* dict = (NSDictionary*)JSON;
...
}
This is really very odd.
We're accessing a json Twitter API that always returns an array.
ie
https://twitter.com/statuses/user_timeline/485963081.json
We do:
if([NSJSONSerialization class]) {
NSError *error = nil;
jsonResponse = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:&error];
DLog(#"JSON Parsing Error: %#", error);
} else {
NSString * jsonString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
jsonResponse = [jsonString JSONValue];
}
if([jsonResponse count] > 0) {
NSString *jsonText = [[jsonResponse objectAtIndex:0] objectForKey:#"text"];
twitterText = jsonText;
}
This works a vast majority of the time. The rest, we get this:
[__NSCFDictionary objectAtIndex:]: unrecognized selector sent to instance
Note, all the errors are on iOS5, so the SBJSON library does not apply.
Sometimes NSJSONSerialization parses the array as a dict. Which frankly, is not possible using the data from twitter. So what's happening here?