Accessing JSON data inside an NSDictionary generated from NSJSONSerialization - objective-c

Having some trouble accessing the JSON data in the following URL ( http://jamesstenson.com/portraits/?json=1 ), basically I want to access the "full" "url"'s underneath "attachments". My code at the moment is as follows:
NSError *e = nil;
NSData *jsonFeed = [NSData dataWithContentsOfURL:[NSURL URLWithString:#"http://jamesstenson.com/portraits/?json=1"]];
NSDictionary *jsonData = [NSJSONSerialization JSONObjectWithData:jsonFeed options:NSJSONReadingMutableContainers error: &e];
if (!jsonData) {
NSLog(#"Error parsing JSON: %#", e);
} else {
for(NSDictionary *item in [jsonData objectForKey:#"page"]) {
for(NSDictionary *attachment in [item objectForKey:#"images"]) {
NSLog(#"%#", attachment);
}
}
}
This keeps throwing up an error:
2011-12-21 10:13:39.362 JSON[3463:f803] -[__NSCFString objectForKey:]: unrecognized selector sent to instance 0x6a7b500
2011-12-21 10:13:39.363 JSON[3463:f803] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString objectForKey:]: unrecognized selector sent to instance 0x6a7b500'
I am aware I am accessing the items wrongly, but cannot figure out how to achieve this. I've tried several solutions such as http://blogs.captechconsulting.com/blog/nathan-jones/getting-started-json-ios5 - but no luck. I am complete newbie to iOS development and have a little knowledge of JSON. Thanks for everyones help in advance.

The problem is in you for loop
for(NSDictionary *item in [jsonData objectForKey:#"page"])
You won't get NSDictionary in item, it will return you key of Dictionary, which would be NSString
Check this link for each loop in objective c for accessing NSMutable dictionary to know how to traverse through NSDictionay
Below is the modified code for your requirement, might help you
if (!jsonData) {
NSLog(#"Error parsing JSON: %#", e); } else {
NSArray *attachments = [[jsonData objectForKey:#"page"] objectForKey:#"attachments"];
for(NSDictionary *object in attachments) {
NSLog(#"%#", [object objectForKey:#"images"]);
NSLog(#"%#", [[[object objectForKey:#"images"] objectForKey:#"full"] objectForKey:#"url"]);
}
}

Related

Replacing stuff in JSON string

Why do I get an error with this:
NSString *jsonString = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSLog(#"jsonRoster unmasked: %#", jsonString);
NSString *maskedString = [self maskJSON:jsonString withMultipleElementStartString:#"###multipleElementsBegin###" andMultipleEndString:#"###multipleElementsEnd###" andSingleElementStartString:#"###elementBegin###" andSingleElementEndString:#"###elementEnd###"];
NSLog(#"jsonRoster masked: %#", maskedString);
Here is the error:
Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: '-[__NSDictionaryI
stringByReplacingOccurrencesOfString:withString:]: unrecognized
selector sent to instance 0x600002932400'
But why, is the string still a Dictionary?
As per error message JSONObjectWithData returned an NSDictionary object, in fact it is in practice so, JSONObjectWithData returns a dictionary or an array depending on your JSON structure. So you should normally check return type and handle it properly.
Edit
To get an NSString you can use its initWithData:encoding: method.

Send NSMutableArray of NSMutableDictionary data using NSURLRequest

This is my request body
[
{
"DealId":677304,
"CustomerId":328702,
"CouponQtn":1,
"PaymentType":"MPD",
"CustomerMobile":"01670234032",
"CustomerAlternateMobile":"01670234032",
"CustomerBillingAddress":"IT test order.......",
"Sizes":"not selected",
"Color":"",
"DeliveryDist":62,
"CardType":"Manual",
"OrderFrom":"iOS",
"MerchantId":14025,
"OrderSource":"app",
"AdvPaymentType":0,
"AdvPayPhoneId":0,
"deliveryCharge":45,
"OrderCouponPrice":500
}
]
I am trying to send NSMutableArray of NSMutableDictionary data using NSURLRequest in a Restful api but my app is getting exceptions like
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayM bytes]: unrecognized selector sent to instance 0x600000855e40'.
My Parsing code :
-(NSDictionary*)getDataByPOST:(NSString*)url parameter:(id)parameter{
NSDictionary *dictionaryData;
NSDictionary *dic;
Reachability *reachTest = [Reachability reachabilityWithHostName:#"www.apple.com"];
NetworkStatus internetStatus = [reachTest currentReachabilityStatus];
if ((internetStatus != ReachableViaWiFi) && (internetStatus != ReachableViaWWAN)){
dictionaryData = [[NSDictionary alloc] initWithObjectsAndKeys:#"error",#"status",#"No Network",#"message",nil];
dic = [NSDictionary dictionaryWithObjectsAndKeys:dictionaryData, #"response",nil];
return dic;
}
else{
NSURL *s =[self getAbsoluteURL:url];
NSMutableURLRequest *requestURL = [NSMutableURLRequest requestWithURL:s cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:900.00];
//NSLog(#"%#",requestURL);
[requestURL setHTTPMethod:#"POST"];
NSError *error=nil ;
if ([parameter isKindOfClass : [NSString class]]) {
[requestURL setHTTPBody:[parameter dataUsingEncoding:NSUTF8StringEncoding]];
}
else if([parameter isKindOfClass:[NSDictionary class]]) {
[requestURL setHTTPBody:parameter];
}
else {
[requestURL setHTTPBody:parameter];
}
NSHTTPURLResponse *response;
NSError *error1=nil;
// NSLog(#"%#\n\n%#",s,parameter);
NSData *apiData = [NSURLConnection sendSynchronousRequest:requestURL returningResponse:&response error:&error1];
if (!apiData) {
NSLog(#"Error: %#", [error localizedDescription]);
return NO;
}
if (response.statusCode == 0) {
dictionaryData = [[NSDictionary alloc] initWithObjectsAndKeys:#"error",#"status",#"Server Error",#"message",nil];
return dic;
}
else if(response.statusCode == 404) {
dictionaryData= [[NSDictionary alloc] initWithObjectsAndKeys:#"error",#"status",#"Server is Currently Down.",#"message", nil];
return dic;
}
else {
dictionaryData = [NSJSONSerialization JSONObjectWithData:apiData options:0 error:&error];
}
}
return dictionaryData;
}
And here is my api calling code
tempDic = [apiCom getNodeDataByPOST:CART_ORDER_URL parameter:orderArray];
Here orderArray is NSMutableArrray contains NSMutableDictionary objects.
Thanks
You got the error:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayM bytes]: unrecognized selector sent to instance 0x600000855e40'.
This means that at some point in your code you thought you could use the bytes method (getter) on a object that has it, but in fact the object is a NSMutableArray one, and since it doesn't implement bytes, your code crash with that error. Now, bytes is for instance a NSData method. I'll get back to it.
As a developer, you need to locate the lines causing that crashes. Even if you don't understand it, if you pinpoint the issue, others might be happier to help because they can focus on the issue and not lose time looking on big portion of code hoping to find the issue. And even if it's not for others, do it for you.
That's not a negative critic, that's a tip.
Culprit lines:
if ([parameter isKindOfClass : [NSString class]]) {
[requestURL setHTTPBody:[parameter dataUsingEncoding:NSUTF8StringEncoding]];
}
else if([parameter isKindOfClass:[NSDictionary class]]) {
[requestURL setHTTPBody:parameter];
}
else {
[requestURL setHTTPBody:parameter];
}
Doc of NSMutableURLRequest:
#property(copy) NSData *HTTPBody;
So clearly, if parameter is a NSDictionary, or a NSArray you'll get that same crash, with either: -[__NSDictionary bytes]: unrecognized selector sent to instance (or similar, with a I or a M somewhere in the class name for Mutable/Immutable or Single for optimized Dictionary/Array, etc.)
Now, it depends on the doc of your Web API:
A common usage is to use JSON:
else if([parameter isKindOfClass:[NSDictionary class]] || [parameter isKindOfClass:[NSArray class]]) {
[request setHTTPBody:[NSJSONSerialization dataWithJSONObject:parameter options:0 error:nil]];
}
I used nil for the error, but it might be interesting to check its value in case of failure.

Parsing JSON objects error

I have this JSON.
{
"cnt": 1,
"list": [
{
"object1": [
{
"subobject1": "value1",
"subobject2": "value2",
"subobject3": "value3"
}
],
"object2": {
"subobject1": value1,
"subobject1": value2,
"subobject1": value3
}
}
]
}
I can't get data from the first object. I receive an error
-[__NSArrayM objectForKeyedSubscript:]: unrecognized selector sent to instance 0x7fa281f82520
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayM objectForKeyedSubscript:]: unrecognized selector sent to instance 0x7fa281f82520'
For the other object I get the data and I can see it in the NSLOG, but can't understand what's the problem with the first one and why the app is crashing.
This is how I parse the json in the DataModel
NSError *deserializationError;
NSMutableDictionary *json = [NSJSONSerialization JSONObjectWithData:data options: NSJSONReadingMutableContainers error: &deserializationError];
NSArray * responseArr = json[#"list"];
NSMutableArray *result = [[NSMutableArray alloc] init];
if(responseArr && [responseArr isKindOfClass:[NSArray class]]) {
for(NSDictionary *cDictionary in responseArr) {
DAObject *cty = [[DAObject alloc] initWithDictionary:ctyDictionary];
if(cty) {
[result addObject:cty];
}
}
}
then In the Object .m file
DAServiceObject *object1 = [[DAServiceObject alloc] initWithDictionary:dictionary[#"object1"]];
self.value1 = object1.value1;
self.value2 = object1.value2;
and the app crashes.
You misinterpreted the data structure: "list" contains an array with only one item, i.e. a dictionary. This dictionary contains an array for each key (e.g. "item1"), again with only one item (again a dictionary).
edit
// ...
if(responseArr && [responseArr isKindOfClass:[NSArray class]]) {
NSDictionary *content = responseArr[0];
for (NSSString *key in [content allKeys]) {
NSDictionary *a = content[key][0];
// ...
}
}
Your JSON data is not an array. It is a dictionary. It's a dictionary with one key "cnt" and one key "list". The object under key "list" is an array.

How to parse this JSON response into a key & value pairs array

there are a lot of questions like this and i'm experienced with json format too but i couldnt parse the response below(at the bottom):
I'm using NSJSONSerialization for parsing the response into NSDictionary but the it gives the error like below:
My code:
NSString *subURL= sharedDa.ip;
NSData *data=[NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"http://192.168.69.230/tsadmin.php?tssearch=%#", subURL]]];
NSError *error=nil;
NSDictionary* portsResult=[NSJSONSerialization JSONObjectWithData:data options:
NSJSONReadingMutableContainers error:&error];
NSDictionary * tempPorts;
NSString *k;
for(k in [portsResult allKeys]){
tempPorts = [portsResult objectForKey:k];
NSLog(#"Temporary ports: %#", tempPorts);
}
And the error code is below:
2012-09-28 18:47:37.508 BNTPRO ST Manager[2609:fb03] -[__NSArrayM allKeys]: unrecognized selector sent to instance 0x6b83ed0
2012-09-28 18:47:37.511 BNTPRO ST Manager[2609:fb03] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayM allKeys]: unrecognized selector sent to instance 0x6b83ed0'
*** First throw call stack:
(0x1568022 0x1b20cd6 0x1569cbd 0x14ceed0 0x14cecb2 0x57cd 0x28fa1e 0x28fd11 0x2a18fd 0x2a1aef 0x2a1dbb 0x2a285f 0x2a2e06 0x2a2a24 0x3e59 0x2595c5 0x2597fa 0xaee85d 0x153c936 0x153c3d7 0x149f790 0x149ed84 0x149ec9b 0x245a7d8 0x245a88a 0x1c8626 0x26d2 0x2645 0x1)
terminate called throwing an exception(lldb)
now my data snippet is: [{"k1":{"v":"0"}},{"k2":{"v":"0"}},{"k3":{"v":"0"}},{"k4":{"v":"0"}},{"k5":{"v":"0"}},{"k6":{"v":"0"}},{"k7":{"v":"1"}},{"k8":{"v":"0"}},{"k9":{"v":"1"}},{"k10":{"v":"0"}},{"k11":{"v":"1"}},{"k12":{"v":"0"}},{"k13":{"v":"1"}},{"k14":{"v":"0"}},{"k15":{"v":"0"}},{"k16":{"v":"0"}}]
but it still gives the same error.. even i decşare the iVar as NSDictionary why does it complain of nsmutable array??
The JSON you're parsing is an array, not an object. So the result of [NSJSONSerialization JSONObjectWithData...] is not an NSDictionary *, but an NSArray * instead.
For example, for the JSON data
[{"k1":{"v":"0"}}, {"k2":{"v":"0"}}]
You can use something similar to this code (don't have xcode right now to try to run it):
NSArray * arr = [NSJSONSerialization JSONObjectWithData:data options:...];
int i;
for (i = 0; i < [arr count]; i++) {
NSDictionary * dic = [arr objectAtIndex:i];
NSString * k;
for (k in [dic allKeys]) {
NSLog(#"Temporary ports: %#", [dic objectForKey:k]);
}
}

Error in NSMutableArray

I am very new to ios development, I am trying to add some values from NSMutableDictionary to NSMutableArray, when I run the code I get this error
2012-05-29 14:09:34.913 iShop[7464:f803] -[__NSCFArray objectForKey:]:
unrecognized selector sent to instance 0x6e423d0 2012-05-29
14:09:34.915 iShop[7464:f803] * Terminating app due to uncaught
exception 'NSInvalidArgumentException', reason: '-[__NSCFArray
objectForKey:]: unrecognized selector sent to instance 0x6e423d0'
* First throw call stack: (0x13cb022 0x155ccd6 0x13cccbd 0x1331ed0 0x1331cb2 0x2bb7 0x13cce42 0x93b9df 0x139f94f 0x1302b43 0x1302424
0x1301d84 0x1301c9b 0x12b47d8 0x12b488a 0x15626 0x28bd 0x2825)
terminate called throwing an exception(lldb)
below is my code:
-(void) getData:(NSData *) response {
NSError *error;
NSMutableDictionary *json = [NSJSONSerialization JSONObjectWithData:response options:kNilOptions error:&error];
//NSLog(#"%#", json);
jsonArray = [[NSMutableArray alloc] init];
jsonArray = [json objectForKey:#"Name"];
NSLog(#"%#", jsonArray);
}
- (void)viewDidLoad {
[super viewDidLoad];
jsonURL = [NSURL URLWithString:#"http://localhost:8888/read_product_list.php"];
dispatch_async(BgQueue, ^{
NSData* data = [NSData dataWithContentsOfURL:jsonURL];
[self performSelectorOnMainThread:#selector(getData:)
withObject:data waitUntilDone:YES];
});
}
JSONObjectWithData return an object of type id. depending on the structure of your received json data.
The data recieved is eiher NSDictionary or NSArray. In your case I am guessing the top level object is of type NSArray which does not respond to objectForKey