iphoneiosjsoncocoa-touchjsonkit

JSONKit giving parse error but JSONLint.org says it's valid


Here's my post.json file:

[
    {
        "Title": "Introduction to WCF",
        "Url": "http://myaddress/videos/introduction-to-wcf",
        "Thumbnail": "http://myaddress/images/20110212_01.jpg",
        "Exceprt": "Introduction to WCF",
        "PostDate": "2011-02-12T14:26:07",
        "Id": 39,
        "Mp4Video": "http://myaddress/2012/05/20110212_01.mp4",
        "Speakers": [
            {
                "Name": "Mark Wilkinson",
                "Slug": "mark-wilkinson"
            }
        ],
        "Groups": [
            {
                "Name": "C# UG",
                "Slug": "cs-ug"
            }
        ],
        "Tags": [
            {
                "Name": "WCF Services",
                "Slug": "wcf-services"
            }
        ]
    }
]

post this in jsonlint.org and it validates.

Here's the code that I've been using for other JSON files that has worked:

- (void)test_can_read_from_groups_file_and_build_JSONDictionary {

    id result = [self data_from_JSON_file:@"post"];
    [Assert isNotNil:result];  // is returning as nil, so test is failing
}

- (id)data_from_JSON_file:(NSString *)fileName {

    NSBundle *bundle = [NSBundle bundleForClass:[self class]];
    NSString *jsonString = [bundle pathForResource:fileName ofType:@"json"];
    NSData *data = [NSData dataWithContentsOfFile:jsonString];
    JSONDecoder *decoder = [[JSONDecoder alloc] initWithParseOptions:JKParseOptionNone];

    NSError *error = nil;
    id result =  [decoder objectWithData:data error:&error];
    if (error) {
        NSLog(@"*********\r\r\r\r\r\r\r Error was: %@", [error localizedDescription]);
    }

    return result;
}

error that is printed out from JSONKit objectWithData:

Error was: Unexpected token, wanted '{', '}', '[', ']', ',', ':', 'true', 'false', 'null', '"STRING"', 'NUMBER'.

ETA: yes it's in the build phases:

enter image description here

added:

if (!data)
{
    NSLog(@"\r\r\r\r\r\r%s: data was nil", __FUNCTION__);
    return nil;
}

It's not hitting this branch so data is not nil.

Changed using JSONKit decoder to this:

id results = [NSJSONSerialization JSONObjectWithData:data
                                                 options:kNilOptions error:&error];

and it works, still perplexed as to why JSONKit is failing for me but not for Rob.


Solution

  • As pst pointed out, the problem turned out to be the BOM. In Xcode, if you right-click on the filename, choose "Open As" and choose "Hex", you'll see:

    hex dump

    Those first three characters are obviously not standard text characters. Fortunately, you can highlight these three characters in the hex editor in Xcode, delete them, save the file, and it will now that should fix it.


    Original answer:

    Also, are you sure the JSON was included in your bundle (check "Copy Bundle Resources" in the "Build Phases" of your "Target Settings). I just parsed your JSON with Cocoa standard JSON parsing class, NSJSONSerialization, without incident. Perhaps you should try examining the data and make sure everything is ok:

    NSLog(@"data=%@", [[[NSString alloc] initWithData:data] autorelease]);
    

    But I parsed your JSON with both JSONKit and NSJSONSerialization without incident.

    NSString *filename = [[NSBundle mainBundle] pathForResource:@"test" ofType:@"json"];
    NSData *data = [NSData dataWithContentsOfFile:filename];
    if (!data)
    {
        NSLog(@"%s: data was nil", __FUNCTION__);
        return;
    }
    JSONDecoder *decoder = [[JSONDecoder alloc] initWithParseOptions:JKParseOptionNone];
    NSError *error = nil;
    id results =  [decoder objectWithData:data error:&error];
    
    //  Also tested with NSJSONSerialization
    //
    //    id results = [NSJSONSerialization JSONObjectWithData:data
    //                                                 options:0
    //                                                   error:&error];
    
    if (!error)
        NSLog(@"%s: results = %@", __FUNCTION__, results);
    else
        NSLog(@"%s: error = %@", __FUNCTION__, error);