8

Currently I am writing an app (Target iOS 6, ARC enabled) that uses JSON for data transmission and Core Data for persistent storage. The JSON data is generated out of a MySQL database by a PHP script via json_encode.

My Problem is that with data from certain tables the following code fails:

- (NSDictionary *)executeFetch:(NSString *)query
{
    NSURL *requesturl = [NSURL URLWithString:[query stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];

    NSError *dataError = nil;
    self.jsonData = [NSData dataWithContentsOfURL:requesturl options:kNilOptions error:&dataError];

    NSError *error = nil;
    self.jsonSerializationResult = [NSJSONSerialization JSONObjectWithData:self.jsonData options:NSJSONReadingMutableContainers|NSJSONReadingMutableLeaves error:&error];

    return self.jsonSerializationResult;

}

The program always crashes with an EXC_BAD_ACCESS error on the line where it says self.jsonSerializationResult and Instruments says that there was a Zombie detected. I know that this means that some object I send a message to is nil, but I can't find out how to fix it... That's what Instruments has to say:

#   Address Category    Event Type  RefCt   Timestamp   Size    Responsible Library Responsible Caller
0   0xa1b8a70   CFString (mutable)  Malloc  1   00:01.603.081   32  Foundation  -[NSPlaceholderMutableString initWithBytesNoCopy:length:encoding:freeWhenDone:]
1   0xa1b8a70   CFString (mutable)  Release 0   00:01.603.137   0   Foundation  newJSONValue
2   0xa1b8a70   CFString (mutable)  Zombie  -1  00:01.603.259   0   Foundation  newJSONString

My program works with every JSON output except for this one:

{
   "termin":[
      {
         "termin_id":"17",
         "veranstaltung_id":"20",
         "beginn":"2012-09-28 17:00:00",
         "ende":"2012-09-28 18:00:00",
         "freie_pl\u00e4tze":null
      },
      {
         "termin_id":"18",
         "veranstaltung_id":"26",
         "beginn":"2012-09-28 19:00:00",
         "ende":"2012-09-28 20:00:00",
         "freie_pl\u00e4tze":null
      },
      {
         "termin_id":"19",
         "veranstaltung_id":"26",
         "beginn":"2012-09-28 21:00:00",
         "ende":"2012-09-28 22:00:00",
         "freie_pl\u00e4tze":null
      },
      {
         "termin_id":"20",
         "veranstaltung_id":"46",
         "beginn":"2012-09-28 19:00:00",
         "ende":"2012-09-28 20:00:00",
         "freie_pl\u00e4tze":null
      },
      {
         "termin_id":"24",
         "veranstaltung_id":"66",
         "beginn":"2012-09-28 22:00:00",
         "ende":"2012-09-28 22:30:00",
         "freie_pl\u00e4tze":"120"
      }
   ]
}

I thought about some possible error sourced but none seems to be the responsible:

  • jsonData or jsonSerializationResult could be nil: they aren't
  • PHP generated invalid JSON: checked for that with a validator
  • null Values: not a problem with other tables

Has anybody got an idea?

user1071136
  • 15,636
  • 4
  • 42
  • 61

3 Answers3

11

It looks like a bug/shortcoming with NSJSONSerialization. The problem is caused by the escaped unicode characters (freie_pl\u00e4tze instead of freie_plätze). You have two options -

  1. Convert the escaped Unicode to real Unicode characters. Try this SO answer
  2. Use another JSON engine, such as JSONKit. JSONKit also claims to be more performant than NSJSONSerialization.
Community
  • 1
  • 1
user1071136
  • 15,636
  • 4
  • 42
  • 61
  • Thank you very much! That was the only thing I didn't alter while examining the differences between the failing data and the working one... Surprisingly the escaped characters only seem to be a problem for the dictionary keys, not for the values... – Christian Hennen Oct 11 '12 at 16:30
  • BTW, I'm only seeing this if I use the `NSJSONReadingMutableContainers | NSJSONReadingMutableLeaves` options. Is this your experience, too? – Rob Sep 10 '13 at 16:24
  • Hello from `AFNetworking` code comments. :) Thank you, it really helps! – skywinder Feb 09 '14 at 23:58
  • I have been using JSONKit for years. Now the project is almost dead (last update was 2 years ago). Des this Apple's NSJSONSerialization was fixed? Which alternatives so far? TouchJSON is used by Facebook SDK. – loretoparisi Apr 14 '14 at 23:25
  • 1
    Escaped unicode characters has been fixed for `NSJSONSerialization` in iOS 7, see http://openradar.appspot.com/radar?id=2397401#ag9zfm9wZW5yYWRhci1ocmRyFAsSB0NvbW1lbnQYgICAgIDdwwgM – 0xced Dec 30 '15 at 22:04
4

I know this question has been answered but I think some beginners may have the same issue as me and be brought to this question.

The EXC_BAD_ACCESS message was caused by malformed JSON. As I had accidentally used the same name for an Object which causes issues when converting the JSON into a dictionary.

Annoyingly it didn't bring up a formatting error. Here is an example of the JSON that caused the issue:

"levels" : {
    "level1": {
        ....
    },
    "level1": {
        ... << All objects should have different names. This should be called level2.
    },
    "level3": {
        ...
    }

To fix the issue I had to ensure that all objects of the same level had different names.

Max
  • 1,175
  • 3
  • 12
  • 22
1

Just tested NSJSONSerialization today. With iOS 7.1. It is working. No issue found. Looks like Apple fixed the issue.

NSString* jsonString = @"{ \"freie_pl\\u00e4tze\":null}";

NSData* jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];

NSError *error = nil;
NSDictionary* jsonSerializationResult = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers|NSJSONReadingMutableLeaves error:&error];

NSLog(@"%@", jsonSerializationResult);
Xiaochen Du
  • 176
  • 10