1

I have a NSJSONSerialization JSONObjectWithData where I pass a NSData object. As a result I get a NSString instead of an NSDictionary. The complete line I have is:

NSDictionary* jsonDec = [NSJSONSerialization JSONObjectWithData:jData options:NSJSONReadingAllowFragments error:&error];

And the return is:

enter image description here

Why don't I get a NSDictionary back? My backend is PHP on the server...

Thanks in advance!

CyberK
  • 1,568
  • 3
  • 31
  • 44
  • What does the original JSON look like? Your server definitely hasn't accidentally encoded twice and returned a string object? `NSJSONSerialization` should normally return a dictionary or an array, and if you have `NSJSONReadingAllowFragments` set as you do, it will also happily return one of the primitive types if that's all that it finds. – Tommy Dec 13 '13 at 19:28
  • that is the string representation of the dictionary. you could do: NSLog(@"%@",jsonDec); and would see the dict as string in your console log. – thorb65 Dec 13 '13 at 19:31
  • reason: '-[__NSCFString objectForKey:]: unrecognized selector sent to instance. This is the error I get if I try to do the following: [[jsonDec objectForKey:@"result"] valueForKey:@"UserID"] – CyberK Dec 13 '13 at 19:33
  • @CyberK: It seems to me that your server is sending "nested JSON" (for whatever reason). Compare http://stackoverflow.com/questions/16948427/how-can-you-deserialize-an-escaped-json-string-with-nsjsonserialization for a similar issue, perhaps you can use that. – Martin R Dec 13 '13 at 19:44
  • The problem is on the server, which is sending twice-encoded JSON; try posting the PHP code you're using there. – Jesse Rusak Dec 13 '13 at 19:45
  • Server side this is happening: json_encode(array('replyCode'=>'success','result'=>array('UserID' =>'xxx'))); – CyberK Dec 13 '13 at 19:52
  • You should return the result object. Maybe set a response header to indicate Success. – LJ Wilson Dec 13 '13 at 19:53
  • I just echo the value in PHP... Strange thing is that everything looks OK. JSON looks valid etc, only I get a NSString back instead of a NSDictionary... – CyberK Dec 13 '13 at 19:57
  • The issue seems to be on the server side of things. Web requests as JSON should be dictionaries an/or arrays. – LJ Wilson Dec 13 '13 at 20:01
  • EIJay, ok but what is the issue then... – CyberK Dec 13 '13 at 20:01
  • Can you post the PHP code you are using to echo that out? – LJ Wilson Dec 13 '13 at 20:02
  • echo json_encode(array('replyCode'=>'success','result'=>array('UserID' => mysql_insert_id()))); – CyberK Dec 13 '13 at 20:02
  • And what does that look like when you echo that out (raw data)? – LJ Wilson Dec 13 '13 at 20:04
  • { "replyCode": "success", "result": { "UserID": 36 } } – CyberK Dec 13 '13 at 20:09
  • @CyberK Clearly, that's not the whole story on the PHP side, since your code in the comments below shows base64 decoding, etc. Somewhere else, you're re-encoding it as JSON again. – Jesse Rusak Dec 14 '13 at 14:58
  • Yes I know, but what I do is: json_encode, then base64 that json, encode it with AES256, and then base64 that again. That is returned. On iOS I do the same process, but then decoding. And there I can see the result as a string in JSON, but if I then put that in the NSJSONSerializer I get the string back instead of the dictionary... If I put that again in an NSJSONSerializer, I get an array back. Problem is that the request sends multiple possibilities back. So one time that works, other time putting it 2 times in the serializer it fails... – CyberK Dec 14 '13 at 20:29

2 Answers2

1
NSDictionary *jsonDec;
NSError* error = nil;
jsonDec = [NSJSONSerialization JSONObjectWithData: jData
                                          options: NSJSONReadingMutableContainers
                                            error: &error];

if (error)
{
     NSLog(@"Error: %@",error);
}

Apple doc: NSJSONReadingMutableContainers - Specifies that arrays and dictionaries are created as mutable objects.

user2828120
  • 233
  • 4
  • 13
  • Error Domain=NSCocoaErrorDomain Code=3840 "The operation couldn’t be completed. (Cocoa error 3840.)" (JSON text did not start with array or object and option to allow fragments not set.) UserInfo=0x10d25c950 {NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.} – CyberK Dec 13 '13 at 19:32
  • your variable that you want to serialize – user2828120 Dec 13 '13 at 19:41
  • NSString *decodedString = [[NSString alloc] initWithData:decMutData encoding:NSUTF8StringEncoding]; NSData *jData = [NSData dataFromBase64String:decodedString]; – CyberK Dec 13 '13 at 19:43
  • you mess up encodings. – user2828120 Dec 13 '13 at 19:44
  • why is that? What do I mess up? – CyberK Dec 13 '13 at 19:45
  • What does mutability have to do with his problem? – Jesse Rusak Dec 13 '13 at 19:46
  • check this code: NSData* jData = [NSData dataWithContentsOfURL:(NSURL *)] – user2828120 Dec 13 '13 at 19:46
  • That's not possible, the return string is decrypted before I get to this point so I cannot simply call dataWithContentsOfURL. I use AFNetworking – CyberK Dec 13 '13 at 19:49
  • Or check this code: NSData *jData = [[NSData alloc] initWithData:decMutData]; – user2828120 Dec 13 '13 at 19:49
  • if not help - check the coding on the server – user2828120 Dec 13 '13 at 19:56
  • The [NSData dataFromBase64String is an extension on NSData. – CyberK Dec 13 '13 at 19:56
  • I do not understand for what you use this method... If you use AFNetworking: success block: (void (^)(NSURLRequest *request, NSHTTPURLResponse *response, id JSON))success. jData = JSON – user2828120 Dec 13 '13 at 20:02
  • because my return value is a AES256 encrypted string, it first gets decrypted into a base64 string etc... But we are going off topic here I think ;-) – CyberK Dec 13 '13 at 20:10
0

I use this when consuming JSON responses (mine usually are arrays of dictionaries). I prefer to use object type id and just use introspection to determine whether it is an NSArray or NSDictionary. BTW - my web requests are either done using AFNetworking (v2) or using the Azure SDK.

id jsonDec = [NSJSONSerialization JSONObjectWithData:jData options:0 error:&error];
LJ Wilson
  • 14,445
  • 5
  • 38
  • 62
  • What is your answer differs from mine? – user2828120 Dec 13 '13 at 19:43
  • 1
    Well you assign the serialized object into an `NSDictionary` which most of the time is a mistake. Unless you know that all your responses will be a JSON dictionary, you should use id and then find out what you have. Most of my requests end up as an `NSArray` of dictionaries. You also use the option to create mutable objects which is not as efficient as using the immutable counterparts. – LJ Wilson Dec 13 '13 at 19:50
  • And BTW - I DID NOT down-vote your answer. I really wish that when people down-vote an answer, the person also leaves a comment explaining why. – LJ Wilson Dec 13 '13 at 19:51
  • id is giving me the exact same result as if I wrote NSDictionary – CyberK Dec 13 '13 at 20:00
  • 1
    While this is a reasonable practice, I don't think it has anything to do with the problem the OP is having. – Jesse Rusak Dec 14 '13 at 15:00