Max
Max

Reputation: 111

How do I traverse a multi dimensional NSArray?

I have array made from JSON response.

NSLog(@"%@", arrayFromString) gives the following:

{ meta = { code = 200; }; response = { groups = ( { items = ( { categories = ( { icon = "http://foursquare.com/img/categories/parks_outdoors/default.png"; id = 4bf58dd8d48988d163941735;

and so on...

This code

NSArray *arr = [NSArray arrayWithObject:[arrayFromString valueForKeyPath:@"response.groups.items"]];

gives array with just one element that I cannot iterate through. But if I write it out using NSLog I can see all elements of it.

At the end I would like to have an array of items that I can iterate through to build a datasource for table view for my iPhone app.

How would I accomplish this?

EDIT:

I have resolved my issue by getting values from the nested array (objectAtIndex:0):

for(NSDictionary *ar in [[arrayFromString valueForKeyPath:@"response.groups.items"] objectAtIndex:0]) {
        NSLog(@"Array: %@", [ar objectForKey:@"name"]);
    }

Upvotes: 1

Views: 1120

Answers (2)

ipmcc
ipmcc

Reputation: 29946

Looking at the JSON string you posted, response.groups.items looks to be an array containing one item, a map/dictionary containing one key, "categories." Logging it out to a string is going to traverse the whole tree, but to access it programmatically, you have to walk the tree yourself. Without seeing a more complete example of the JSON, it's hard to say exactly what the right thing to do is here.

EDIT:

Traversing an object graph like this is not that simple; there are multiple different approaches (depth-first, breadth-first, etc,) so it's not necessarily something for which there's going to be a simple API for you to use. I'm not sure if this is the same JSON library that you're using, but, for instance, this is the code from a JSON library that does the work of generating the string that you're seeing. As you can see, it's a bit involved -- certainly not a one-liner or anything.

You could try this, which I present without testing or warranty:

void __Traverse(id object, NSUInteger depth)
{
    NSMutableString* indent = [NSMutableString string];

    for (NSUInteger i = 0; i < depth; i++) [indent appendString: @"\t"];

    id nextObject = nil;

    if ([object isKindOfClass: [NSDictionary class]])
    {
        NSLog(@"%@Dictionary {", indent);
        NSEnumerator* keys = [(NSDictionary*)object keyEnumerator];

        while (nextObject = [keys nextObject])
        {
            NSLog(@"%@\tKey: %@ Value: ", indent, nextObject);
            __Traverse([(NSDictionary*)object objectForKey: nextObject], depth+1);
        }
        NSLog(@"%@}", indent);
    }
    else if ([object isKindOfClass: [NSArray class]])
    {
        NSEnumerator* objects = [(NSArray*)object objectEnumerator];
        NSLog(@"%@Array (", indent);
        while (nextObject = [objects nextObject])
        {
            __Traverse(nextObject, depth+1);
        }        
        NSLog(@"%@)", indent);
    }
    else 
    {
        NSLog(@"%@%@",indent, object);
    }
}

void Traverse(id object)
{
    __Traverse(object, 0);
}

Upvotes: 1

fjoachim
fjoachim

Reputation: 906

First, the data structure you get back from the JSON parser is not an array but a dictionary: { key = value; ... } (curly braces).

Second, if you want to access a nested structure like the items, you need to use NSObject's valueForKeyPath: method. This will return an array of all items in your data structure:

NSLog(@"items: %@", [arrayFromString valueForKeyPath:@"response.groups.items"]);

Note that you will loose the notion of groups when retrieving the item objects like this.

Upvotes: 1

Related Questions