18

I did a few tests with TouchJSON last night and it worked pretty well in general for simple cases. I'm using the following code to read some JSON content from a file, and deserialize it:

NSString *jsonString = [[NSString alloc] initWithContentsOfFile:@"data.json"];
NSData *jsonData = [jsonString dataUsingEncoding:NSUTF32BigEndianStringEncoding];
NSError *error = nil;
NSDictionary *items = [[CJSONDeserializer deserializer] deserializeAsDictionary:jsonData error:&error];
NSLog(@"total items: %d", [items count]);
NSLog(@"error: %@", [error localizedDescription]);

That works fine if I have a very simple JSON object in the file (i.e. a dictionary):

{"id": "54354", "name": "boohoo"}

This way I was able to get access to the array of values, as I wanted to get the item based on its index within the list:

NSArray *items_list = [items allValues];
NSString *name = [items_list objectAtIndex:1];

(I understand that I could have fetched the name with the dictionary API)

Now I would like to deserialize a semi-complex JSON string, which represents an array of dictionaries. An example of such a JSON string is below:

[{"id": "123456", "name": "touchjson"}, {"id": "3456", "name": "bleh"}]

When I try to run the same code above against this new content in the data.json file, I don't get any results back. My NSLog() call says "total items: 0", and no error is coming back in the NSError object.

Any clues on what is going on? I'm completely lost on what to do, as there isn't much documentation available for TouchJSON, and much less usage examples.

jpm
  • 16,622
  • 34
  • 63
  • 66

5 Answers5

12

I'm the author of TouchJSON.

Your outermost object should be a dictionary and NOT an array. Anything other than a dictionary is not legal. If you have to have an array as the outermost object then use the method (which is technically deprecated, but isn't going any where soon)

- (id)deserialize:(NSData *)inData error:(NSError **)outError;

See: http://www.json.com/json-schema-proposal/ for more information abotu what is and is not legal JSON.

schwa
  • 11,962
  • 14
  • 43
  • 54
  • I appreciate your response to my question, first of all. I was surprised to hear that the outermost object cannot be an array, as I have been doing this type of JSON result for a long time now, and most times things work out just fine with other libraries. Continuing on a separate comment... – jpm Nov 14 '08 at 04:32
  • 4
    According to the JSON RFC created by Douglas Crockford himself (http://www.ietf.org/rfc/rfc4627.txt), arrays as outermost objects are perfectly valid. See Page 7/8 for an actual example in there. – jpm Nov 14 '08 at 04:33
  • 1
    See http://robubu.com/?p=24 for more info. Top level arrays ought to be avoided. Regardless TouchJSON can process them - see the API i listed above. – schwa Nov 14 '08 at 05:15
  • 3
    Well, can we at least agree that it is perfectly "legal" to have arrays as the outermost object? What that post is describing is a browser javascript interpreter vulnerability. Arrays are perfectly legal, but maybe just not officially supported by your library. – jpm Nov 14 '08 at 14:42
  • 2
    In most languages it is also perfectly legal to do something like `++i--;` that does not mean it is good practice. Similarly, it is not a good practice to deserialize a straight array that is not an object. Just because you can does not mean you should. – wisequark Nov 14 '08 at 17:42
  • As long as it's legal to have array as outermost objects, the library should expect it to happen. It doesn't matter if it's a good idea, if it's valid in the specification, someone is going to use it, and us user of the library can't very well tell the JSON provider to change the way they generate their JSON most of the time. – Ben Aug 17 '11 at 13:27
  • Hey guys do we have an answer for this? is the top level array really illegal? In my opinion good practice and legal are totally different, kind of confused.. – zchenah May 16 '12 at 06:53
8

This isn't an answer, but a pointer to a different framework:

http://code.google.com/p/json-framework/

I've been using it quite a bit lately, serializing and de-serializing complex data structures from third-party services such as Google Local and between my own Objective-C and Perl code with absolutely no problems. Not to mention that the API is ridiculously easy to deal with.

Good luck!

rpj
  • 2,380
  • 2
  • 17
  • 30
0

Not sure if it helps you but check this out http://tempered.mobi/%20

alecnash
  • 1,750
  • 1
  • 18
  • 42
0

At it's heart JSON deals with objects, your code to de-serialize should be as follows

{
  "objects": [{
    "id": "123456",
    "name": "touchjson"
  }, {
    "id": "3456",
    "name": "bleh"
  }]
}

which does work with the latest checkout.

Mickael Lherminez
  • 679
  • 1
  • 10
  • 29
wisequark
  • 3,288
  • 20
  • 12
  • 2
    A good json framework should be able to handle either an object or an array as the high level container for the data structure – seanalltogether Nov 14 '08 at 03:49
  • @sean - that's not true. Technically JSON with an array as a high level container is NOT legal JSON. – schwa Nov 14 '08 at 04:09
  • 3
    schwa, says who? http://www.ietf.org/rfc/rfc4627.txt?number=4627 "A JSON text is a serialized object or array. JSON-text = object / array" "5. Generators A JSON generator produces JSON text. The resulting text MUST strictly conform to the JSON grammar." That doc even has top level array exampl – seanalltogether Nov 14 '08 at 04:47
  • See http://robubu.com/?p=24 - "Safe JSON" is JSON with a top level dictionary. There are vulnerabilities with top level arrays. – schwa Nov 14 '08 at 05:14
  • 2
    http://directwebremoting.org/blog/joe/2007/03/06/json_is_not_as_safe_as_people_think_it_is_part_2.html There are vulnerabilities with Objects as well, but this is a browser sandbox issue, not a JSON issue. 'Legal' JSON is array or object. – seanalltogether Nov 14 '08 at 06:07
0

@Mathieu - I think this is what you are looking for (6 months late, I know :), but I just ran into the same problem)

Copy and pasted from here: http://groups.google.com/group/touchcode-dev/browse_thread/thread/ada885832019f45b

NSArray *tweetsArray = [resultsDictionary objectForKey:@"results"]; 
for (NSDictionary *tweetDictionary in tweetsArray) { 
  NSString *tweetText = [tweetDictionary objectForKey:@"text"]; 
  [tweets addObject:tweetText]; 
} 

To give more context, the JSON that I'm parsing is in the general form
of:

{"results": 
   [ 
     {"text":"tweet1"}, 
     {"text":"tweet2"}, 
     {"text":"tweet3"} 
   ] 
} 
sth
  • 222,467
  • 53
  • 283
  • 367
gene tsai
  • 432
  • 3
  • 3