user3060636
user3060636

Reputation: 272

NSArray handled as NSDictionary

I am doing an HTTP call to my web server via objective-c app. The server returned json usually looks like this:

{
  "name": "test",
  "surname": "test",
}

but sometimes, when I am requesting a list of something, I get the JSON like this:

[
  { "name": "test" },
  { "name": "test" },
]

Now, I am handling the returned object as NSDictionary this way:

NSDictionary *results = [http doRequestWithData:@{ @"tag": @"whatever" } atUrl:@"/search"]
NSLog(@"%@", results);

I have omitted the implementation of doRequestWithData for simplicity, because the interesting part of it is that when I do an NSLog of data, I get the following:

(
        {
        "_id" = 5353c332339a5ea32e000008;
        content = "i am the first search result";
    },
        {
        "_id" = 5353c32b339a5ea32e000007;
        content = "I am the second";
    },
        {
        "_id" = 5353c31c339a5ea32e000006;
        content = "third";
    },
)

Can anyone explain how this can happen? The returned data is an NSDictionary, but from the console it seems just like an array, as I cannot see the keys!


UPDATE: I am using NSJSONSerialization in my http class to serialize the object. The docs say it may return either a dict or an array based on the data. but the problem is that I am clearly defining it as NSDictionary! Shouldn't this at least throw and error? This is what I am using in my http class to define the returned nsdictionary:

NSDictionary *responseDict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
return responseDict;

Upvotes: 0

Views: 88

Answers (2)

axiixc
axiixc

Reputation: 1972

Your best bet is to do your own type checking on returned value using isKindOfClass:.

NSData *data = ...;

NSError *__autoreleasing jsonError;
NSDictionary *dictionary = data ? [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&jsonError] : nil;

if (jsonError || ![dictionary isKindOfClass:[NSDictionary class]])
    dictionary = nil;

You may want to do more handling than this, but this at least ensures you'll never access the wrong object type.

Upvotes: 0

Sulthan
Sulthan

Reputation: 130102

Unlike Java (and similar languages), there is no runtime type checking in Obj-C.

If your method returns a NSArray and you store it into a NSDictionary, it's not a problem for Obj-C. Until you try to call a method which is not defined for NSArray (e.g. objectForKey:).

Usually, such problems should be cought at compile time, however

+[NSJSONSerialization JSONObjectWithData:...] returns an id (it can return either NSArray or NSDictionary) and id is compatible with any type.

Upvotes: 1

Related Questions