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);
}
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;
...
}
I am doing an authentication by using AFNetworking like below
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
// Parsing will be here
{
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
NSLog(#"ERROR :jason is %#",JSON);
}];
[client enqueueHTTPRequestOperation:operation];
Below is a JSON which received from server
{
"first_name" = A;
"last_name" = B;
}
Question :
How can a parse this JSON in ios. I am stuck because the return from server does not have any tag at all. If its format was
{
"user": {
"first_name": "A",
"last_name": "B",
}
}
I could parse by doing the following
NSArray *userList = [[NSArray alloc] init];
userList = [JSON objectForKey:#"results"];
Any ideas?
"Tag" is not in the terminology of JSON. The complex structure of JSON is negotiated between the sender and receiver (or simply dictated by the sender) and need not follow any particular outline, so long as it parses correctly.
The first quasi-JSON string you quoted would (if it were valid JSON) presumably identify the first and last name of an individual, and you would presumably know that it was a "user" identity, and what user it identified, from the context.
In general, you must approach a JSON string as an onion, peeling one layer at a time. In the case of your first string there is only one layer, an "Object" that maps to an NSDictionary. So, having received the object (and, if necessary, verified that it is indeed an NSDictionary using isKindOfClass, you would cast the id value to an NSDictionary and proceed to use objectForKey or some such to access the values within.
You should utilize the new JSONSerialization class available in iOS5 which makes JSON easy to consume. Below is a quick example grabbing your json and parsing it in the fetchedData method. Resources listed below
//CALL dataWithContentsOfURL ONCE DATA HAS BEEN RECEIVED YOU CAN PARSE THE JSON:
NSError *error = nil;
NSData* data = [NSData dataWithContentsOfURL:kURL options:NSDataReadingUncached error:&error];
if (error) {
NSLog(#"%#", [error localizedDescription]);
} else {
NSLog(#"Data has loaded successfully.");
}
//MORE CODE HERE?
- (void)fetchedData:(NSData *)responseData {
_yourObjectArray = [[NSMutableArray alloc] init];
//parse out the json data
NSError* error;
NSArray* json = [NSJSONSerialization JSONObjectWithData:responseData //1
options:kNilOptions
error:&error];
for(int i=0; i<[json count]; i++){
YourObject *yObject = [[YourObject alloc]init];
NSDictionary* rawData = [json objectAtIndex:i]; //2
yObject.FirstName = [rawData objectForKey:#"first_name"];
yObject.LastName = [rawData objectForKey:#"last_name"];
[_yourObjectArray addObject:yObject];
}
}
SOURCES:
http://developer.apple.com/library/ios/#documentation/Foundation/Reference/NSJSONSerialization_Class/Reference/Reference.html
http://www.raywenderlich.com/5492/working-with-json-in-ios-5
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.