0

Say you do this,

NSString *teste = yourData[@"title"];

no problem if "title" is completely missing in the json: you just get null. If you do this:

NSString *teste = yourData[@"location"][@"city"];

if "city" is missing in the json nest, no problem. if the whole "location" section does not exist, again no problem

However! You'll often see json like this, " largeImage = "<null>"; "

In that case, the app will crash if you are using the code above.

In practice you have to do this:

NSString *imageUrl = nil;
if ([yourResults[thisRow][@"largeImage"] isKindOfClass:[NSDictionary class]])
    imageUrl = yourResults[thisRow][@"largeImage"][@"URL"];

My question was really:

is there some dead clever way to perhaps override the literal syntax (ie, override the underlying message, perhaps??) to cover this problem?

So essentially, make this concept [@"blah"] basically first check that indeed it is a dictionary at hand, before trying the operation.

It's a shame because, effectively, you can never use this wonderful syntax

yourData[@"location"][@"city"]

in practice, due to the problem I outline.

PS sorry for the earlier confusion on this question, fixed by Paramag. below - good one Paramag.

Fattie
  • 27,874
  • 70
  • 431
  • 719

3 Answers3

1

Personally i use with JSON category which returns null instead NSNull so my code looks:

[[json objectForKeyNotNull:@"Key"] objectForKeyNotNull:@"Other"]

As you want to have code shorter, i think i would create the category on NSDictionary which could be used as :

[json objectForPath:@"Key.Value"]

Which would expand the path into the keys.

There is some nice gist which looks like it's doing it:

https://gist.github.com/Yulong/229a62c1188c3c024247#file-nsdictionary-beeextension-m-L68

Krzysztof
  • 1,441
  • 11
  • 22
  • wow two excellent ideas ! in objectForKeyNotNull you could also check isKindOfClass, as in my postscript. – Fattie Aug 13 '14 at 10:34
  • have a look at the link i added to the post. Code looks really good and it's got the Null checks too. – Krzysztof Aug 13 '14 at 10:38
  • good one, just bear in mind though the real problem is the "it's not a dictionary" issue - I clarified my bad question! cheers – Fattie Aug 13 '14 at 11:03
1

to check this kind of null , you can use valueForKeyPath:

NSString *teste = [CLOUD.yourData[thisRow] valueForKeyPath:@"location.city"];

it will first check for "location" and then for "city".

Sri Kanth
  • 51
  • 5
  • a worthy answer, but one problem is "location.city" fails in a weird way you wouldn't expect, if the first one is not a dictionary but is a string - it's a bit annoying. – Fattie Aug 13 '14 at 10:54
0

I would say this is a problem with your schema. null in JSON and a dictionary (called an "object") in JSON are different types of things. The fact that your key can have a value that is sometimes null and sometimes a dictionary seems to me that you guys are not following a rigorous schema.

A good design would have the key either not be there, or if it is there, its value is guaranteed to be a dictionary. In such a case, the Objective-C code NSString *teste = yourData[@"location"][@"city"]; would work without modification because if the key "location" didn't exist, then its value would be nil in Objective-C, and subsequent accesses won't crash, and will also return nil.

newacct
  • 119,665
  • 29
  • 163
  • 224
  • hi NewAcct, right, you've nicely outlined the problem - **"value is guaranteed to be a dictionary..."**, you can't guarantee that in real life on any project, that's the issue. (An everyday example is if you are pulling results from amazon, **for goodness sake!!!**, they often incorrectly return the string "" rather than a real null.) As you imply, of course, in an app, you cannot rely on the json being correct - or you're app will crash all day :) (Assuming I understand what you are saying correctly, sorry if not.) – Fattie Aug 15 '14 at 09:13