How to use NSJSONSerialization

223,824

Solution 1

Your root json object is not a dictionary but an array:

[{"id": "1", "name":"Aaa"}, {"id": "2", "name":"Bbb"}]

This might give you a clear picture of how to handle it:

NSError *e = nil;
NSArray *jsonArray = [NSJSONSerialization JSONObjectWithData: data options: NSJSONReadingMutableContainers error: &e];

if (!jsonArray) {
  NSLog(@"Error parsing JSON: %@", e);
} else {
   for(NSDictionary *item in jsonArray) {
      NSLog(@"Item: %@", item);
   }
}

Solution 2

This is my code for checking if the received json is an array or dictionary:

NSError *jsonError = nil;
id jsonObject = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:&jsonError];

if ([jsonObject isKindOfClass:[NSArray class]]) {
    NSLog(@"its an array!");
    NSArray *jsonArray = (NSArray *)jsonObject;
    NSLog(@"jsonArray - %@",jsonArray);
}
else {
    NSLog(@"its probably a dictionary");
    NSDictionary *jsonDictionary = (NSDictionary *)jsonObject;
    NSLog(@"jsonDictionary - %@",jsonDictionary);
}

I have tried this for options:kNilOptions and NSJSONReadingMutableContainers and works correctly for both.

Obviously, the actual code cannot be this way where I create the NSArray or NSDictionary pointer within the if-else block.

Solution 3

It works for me. Your data object is probably nil and, as rckoenes noted, the root object should be a (mutable) array. See this code:

NSString *jsonString = @"[{\"id\": \"1\", \"name\":\"Aaa\"}, {\"id\": \"2\", \"name\":\"Bbb\"}]";
NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSError *e = nil;
NSMutableArray *json = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&e];
NSLog(@"%@", json);

(I had to escape the quotes in the JSON string with backslashes.)

Solution 4

Your code seems fine except the result is an NSArray, not an NSDictionary, here is an example:

The first two lines just creates a data object with the JSON, the same as you would get reading it from the net.

NSString *jsonString = @"[{\"id\": \"1\", \"name\":\"Aaa\"}, {\"id\": \"2\", \"name\":\"Bbb\"}]";
NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];

NSError *e;
NSMutableArray *jsonList = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&e];
NSLog(@"jsonList: %@", jsonList);

NSLog contents (a list of dictionaries):

jsonList: (
           {
               id = 1;
               name = Aaa;
           },
           {
               id = 2;
               name = Bbb;
           }
           )

Solution 5

[{"id": "1", "name":"Aaa"}, {"id": "2", "name":"Bbb"}]

In above JSON data, you are showing that we have an array contaning the number of dictionaries.

You need to use this code for parsing it:

NSError *e = nil;
NSArray *JSONarray = [NSJSONSerialization JSONObjectWithData: data options: NSJSONReadingMutableContainers error: &e];
        for(int i=0;i<[JSONarray count];i++)
        {
            NSLog(@"%@",[[JSONarray objectAtIndex:i]objectForKey:@"id"]);
             NSLog(@"%@",[[JSONarray objectAtIndex:i]objectForKey:@"name"]);
        }

For swift 3/3+

   //Pass The response data & get the Array
    let jsonData = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! [AnyObject]
    print(jsonData)
    // considering we are going to get array of dictionary from url

    for  item  in jsonData {
        let dictInfo = item as! [String:AnyObject]
        print(dictInfo["id"])
        print(dictInfo["name"])
    }
Share:
223,824

Related videos on Youtube

Logan Serman
Author by

Logan Serman

Updated on July 08, 2022

Comments

  • Logan Serman
    Logan Serman almost 2 years

    I have a JSON string (from PHP's json_encode() that looks like this:

    [{"id": "1", "name":"Aaa"}, {"id": "2", "name":"Bbb"}]
    

    I want to parse this into some sort of data structure for my iPhone app. I guess the best thing for me would be to have an array of dictionaries, so the 0th element in the array is a dictionary with keys "id" => "1" and "name" => "Aaa".

    I do not understand how the NSJSONSerialization stores the data though. Here is my code so far:

    NSError *e = nil;
    NSDictionary *JSON = [NSJSONSerialization 
        JSONObjectWithData: data 
        options: NSJSONReadingMutableContainers 
        error: &e];
    

    This is just something I saw as an example on another website. I have been trying to get a read on the JSON object by printing out the number of elements and things like that, but I am always getting EXC_BAD_ACCESS.

    How do I use NSJSONSerialization to parse the JSON above, and turn it into the data structure I mentioned?

    • d.lebedev
      d.lebedev over 12 years
      your data variable is probably nil
    • Logan Serman
      Logan Serman over 12 years
      It isn't, I have tested that already.
    • Monolo
      Monolo over 12 years
      Have you tried to see if there is any relevant information in the error object?
  • Logan Serman
    Logan Serman over 12 years
    Thanks I will try that, but shouldn't [JSON count] return something instead of just giving me EXC_BAD_ACCESS?
  • rckoenes
    rckoenes over 12 years
    It should, that why I added the check if !jsonArray and printed out the error. This should display any error that occurred during parsing.
  • rckoenes
    rckoenes almost 11 years
    @xs2bush no, since you did not create the jsonArray it should be autorelease.
  • Olie
    Olie over 10 years
    @Logan: Yes, [JSON count] should return a value. See my answer below regarding zombies. EXC_BAD_ACCESS is almost always zombie-related.
  • Thomas Clowes
    Thomas Clowes over 10 years
    In this case, item is the key in a given JSON key value pair.. your for loop works perfectly outputting each of my JSON keys. I however already know the key for the value i want, namely 'key'. My efforts to get the value of this key and output it to the log have failed. Any further insight?
  • rckoenes
    rckoenes over 10 years
    @ThomasClowes You should ask your own question, not ask it in a comment of an answer.
  • Thomas Clowes
    Thomas Clowes over 10 years
    @rckoenes - It is one and the same question. So as not to create a duplicate question i continued the discussion here..
  • Porizm
    Porizm over 10 years
    I think your answer should be the best answer because it seems the fastest way to access the JSON structure.
  • Zar E Ahmer
    Zar E Ahmer over 9 years
    What this option (NSJSONReadingMutableContainers) means . I don kNilOption and everything works fine. Tell me the purpose of using these option
  • zaph
    zaph over 9 years
    Top hit in Google: NSJSONReadingMutableLeaves: "Specifies that leaf strings in the JSON object graph are created as instances of NSMutableString."
  • Zar E Ahmer
    Zar E Ahmer over 9 years
    and what about MutableContainer
  • zaph
    zaph over 9 years
    Oops, again from the top Google result: NSJSONReadingMutableContainers: "Specifies that arrays and dictionaries are created as mutable objects."
  • zaph
    zaph over 9 years
    Also option-click in NSJSONReadingMutableContainers in Xcode, option-double-click for the full documentation.
  • Zorayr
    Zorayr almost 9 years
    Swift 2 on Xcode 7 breaks this -> the migration moves to try/catch error handling.
  • Deepak G M
    Deepak G M over 8 years
    These only help if you plan to modify the returned JSON object and save it back. In either case, the objects are probably autoreleased objects and that seems to be the root cause.
  • Deepak G M
    Deepak G M over 8 years
    The options should not use two | but a single | since they need to be bitwise ORed.
  • jk7
    jk7 over 8 years
    Deepak, you listed NSJSONReadingMutableContainers twice. Did you mean for one to be NSJSONReadingMutableLeaves?
  • Noah Gilmore
    Noah Gilmore over 5 years
    The question does not ask anything about network requests