как перебирать вложенные словари в target-c iphone sdk

Привет, у меня есть строка json, преобразованная без использования фреймворка JSON в словарь, и мне нужно извлечь ее содержимое. Как я могу перейти к вложенным словарям? У меня уже есть этот код, который позволяет мне видеть словарь:

NSDictionary *results = [responseString JSONValue]; 
NSMutableArray *catArray = [NSMutableArray array];

for (id key in results) {
    NSLog(@"key: %@, value: %@", key, [results objectForKey:key]);
    [catArray addObject:key];
    NSString *cat = key;
}

Может ли кто-нибудь предоставить пример того, как добраться до всех уровней dic, не используя имя ключей?

Результирующая структура dic выглядит следующим образом: http://www.freeimagehosting.net/uploads/e7c020d697.png

http://www.freeimagehosting.net/uploads/e7c020d697.png

спасибо

ЛДЖ


person ldj    schedule 23.07.2010    source источник
comment
Извини, я не слежу за тобой.   -  person ldj    schedule 23.07.2010


Ответы (5)


Пытаться



for ((id) key in [results allKeys]) {
    NSLog(@"key: %@, value: %@", key, [results objectForKey:key]);
    [catArray addObject:key];
    NSString *cat = key;
}

Надеюсь, это помогло.

РЕДАКТИРОВАТЬ: я не уверен, правильно ли я понимаю вашу структуру, но я предполагаю, что у вас есть некоторые значения в вашем словаре, которые снова являются словарями. если вы хотите взаимодействовать через словарь, который находится внутри другого, вы можете сделать это следующим образом:


for ((id) key in [results allKeys]) {
    id value = [results objectForKey:key];
    if ([value isKindOfClass:[NSDictionary class]]) {
        NSDictionary* newDict = (NSDictionary*)value;
        for ((id) subKey in [newDict allKeys]) {
            ...
        }
    }
}

Конечно, если вы знаете конкретный ключ к нужному словарю, вы можете проверить его вместо того, чтобы проверять, является ли значение словарем. Но, может быть, неплохо проверить это в обоих случаях...

person Tobi    schedule 26.07.2010
comment
Тоби, спасибо, да, этот код делает то же самое, что и у меня. Меня больше интересует пример, который показывает мне, как я могу получить все ключи в разделе «Искусство» (антиквариат, стеклянная посуда) и с ними получить запись для business_name в свойствах. Можете ли вы отредактировать фрагмент кода для достижения этой цели? Спасибо - person ldj; 27.07.2010

Вероятно, вам придется попробовать рекурсивную функцию.

-(void)recurse:(NSDictionary *)dict counter: (int*) i parent:(NSString *) parent{
    for (NSString* key in [dict allKeys]) {
        id value = [dict objectForKey:key];
        NSLog(@"%@ -> %@", parent, key);
        if ([value isKindOfClass:[NSDictionary class]]) {
            i++;
            NSDictionary* newDict = (NSDictionary*)value;
            [self recurse:newDict counter:i parent:key];
            i--;
        } else {
            //Do smthg
        }
    }
}

это перечислит все ключи и их уровень.

person Denis Mikhaylov    schedule 16.02.2011

Я уверен, что вы уже решили эту проблему, но мне показалось удобным написать рекурсивную функцию служебного класса, которая рекурсивно регистрирует каждый ключ словаря:

/**
 *  Recursively logs the keys and values of each object in the dictionary,
 *  along with the class of the value.
 *
 *  @param dict The dictionary to inspect
 */
+ (void)logDictionaryKeys:(NSDictionary*)dict {
    for (id key in dict) {
        if ([dict[key] isKindOfClass:[NSDictionary class]]) {
            [self logDictionaryKeys:dict[key]];
        }else {
            NSLog(@"Key: %@", key);
            NSLog(@"Value: %@ (%@)", dict[key], [dict[key] class]);
        }
    }

    return;
}
person HighFlyingFantasy    schedule 02.12.2013

Заголовок категории:

#import <Foundation/Foundation.h>

@interface NSDictionary(Find)

-(id) findflat:(NSString*)keyToFind;

@end

Тело:

#import "NSDictionary+Find.h"

@implementation NSDictionary(Find)

-(id) findflat:(NSString*)keyToFind{

    if([self objectForKey:keyToFind])
        return self[keyToFind];

    for(id key in self)
        if([[self objectForKey:key] isKindOfClass:[NSDictionary class]])
            return [[self objectForKey:key] findflat:keyToFind];


    return nil;
}

@end

Использование/проверка:

- (void)testExample {
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct results.

NSDictionary *dic = @{};
XCTAssertNil([dic findflat:@"url"]);

dic = @{@"url":@"http://"};
XCTAssertEqual([dic findflat:@"url"],@"http://");

dic = @{@"other":@4};
XCTAssertNil([dic findflat:@"url"]);

dic = @{@"other":@4,@"url":@"http://"};
XCTAssertEqual([dic findflat:@"url"],@"http://");

dic = @{@"other":@4,@"sd":@"sdf"};
XCTAssertNil([dic findflat:@"url"]);

dic = @{@"other":@4,@"dic":@{@"url":@"http://"}};
XCTAssertEqual([dic findflat:@"url"],@"http://");

dic = @{@"other":@4,@"dic":@{@"sd":@2,@"url":@"http://"}};
XCTAssertEqual([dic findflat:@"url"],@"http://");

dic = @{@"other":@4,@"dic":@{}};
XCTAssertNil([dic findflat:@"url"]);

dic = @{@"other":@4,@"dic":@{@"dic":@{@"sd":@2,@"url":@"http://"}}};
XCTAssertEqual([dic findflat:@"url"],@"http://");

}

person Javier Calatrava Llavería    schedule 02.12.2016

Я попробовал рекурсию и надеюсь, что это поможет.
P.S. Это вернет первое вхождение ключа.

+(id)getValue:(NSDictionary*)aDictionary forKey:(NSString *)aKey {
   id finalValue = nil;
   for (id key in [aDictionary allKeys]) {
      id value = aDictionary[key];
      if (value != nil && [key isEqualToString:aKey]) {
         finalValue = value;
         break;
      }
      else if ([value isKindOfClass:[NSDictionary class]]) {
       finalValue = [[self class] getValue:value forKey:aKey];
      }
   }
   return finalValue;
}
person Abhijit    schedule 13.03.2015