Подтвердить что ты не робот

Заменить все объекты NSNull в NSDictionary

Мне любопытно, у меня в настоящее время есть NSDictionary, где некоторые значения устанавливаются в объект NSNull благодаря помощи json-framework.

Цель состоит в том, чтобы удалить все значения NSNull и заменить его пустой строкой.

Я уверен, что кто-то это сделал? Несомненно, это, вероятно, четыре лайнера, и это просто, я просто слишком сгорел, чтобы понять это самостоятельно.

Спасибо!

4b9b3361

Ответ 1

Действительно просто:

@interface NSDictionary (JRAdditions)
- (NSDictionary *)dictionaryByReplacingNullsWithStrings;
@end

@implementation NSDictionary (JRAdditions)

- (NSDictionary *)dictionaryByReplacingNullsWithStrings {
   const NSMutableDictionary *replaced = [self mutableCopy];
   const id nul = [NSNull null];
   const NSString *blank = @"";

   for(NSString *key in self) {
      const id object = [self objectForKey:key];
      if(object == nul) {
         //pointer comparison is way faster than -isKindOfClass:
         //since [NSNull null] is a singleton, they'll all point to the same
         //location in memory.
         [replaced setObject:blank 
                      forKey:key];
      }
   }

   return [replaced copy];
}

@end

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

NSDictionary *someDictThatHasNulls = ...;
NSDictionary *replacedDict = [someDictThatHasNulls dictionaryByReplacingNullsWithStrings];

Ответ 2

Я внес несколько изменений в исходный ответ Джейкоба, чтобы расширить его, чтобы обрабатывать словари и массивы, хранящиеся в оригинальном словаре.

#import "NSDictionary+NullReplacement.h"
#import "NSArray+NullReplacement.h"

@implementation NSDictionary (NullReplacement)

- (NSDictionary *)dictionaryByReplacingNullsWithBlanks {
    const NSMutableDictionary *replaced = [self mutableCopy];
    const id nul = [NSNull null];
    const NSString *blank = @"";

    for (NSString *key in self) {
        id object = [self objectForKey:key];
        if (object == nul) [replaced setObject:blank forKey:key];
        else if ([object isKindOfClass:[NSDictionary class]]) [replaced setObject:[object dictionaryByReplacingNullsWithBlanks] forKey:key];
        else if ([object isKindOfClass:[NSArray class]]) [replaced setObject:[object arrayByReplacingNullsWithBlanks] forKey:key];
    }
    return [NSDictionary dictionaryWithDictionary:[replaced copy]];
}

@end

А также категория массива, конечно:

#import "NSArray+NullReplacement.h"
#import "NSDictionary+NullReplacement.h"

@implementation NSArray (NullReplacement)

- (NSArray *)arrayByReplacingNullsWithBlanks  {
    NSMutableArray *replaced = [self mutableCopy];
    const id nul = [NSNull null];
    const NSString *blank = @"";
    for (int idx = 0; idx < [replaced count]; idx++) {
        id object = [replaced objectAtIndex:idx];
        if (object == nul) [replaced replaceObjectAtIndex:idx withObject:blank];
        else if ([object isKindOfClass:[NSDictionary class]]) [replaced replaceObjectAtIndex:idx withObject:[object dictionaryByReplacingNullsWithBlanks]];
        else if ([object isKindOfClass:[NSArray class]]) [replaced replaceObjectAtIndex:idx withObject:[object arrayByReplacingNullsWithBlanks]];
    }
    return [replaced copy];
}

@end

С помощью этого вы можете взять любой массив или словарь и рекурсивно уничтожить все экземпляры [NSNull null].

Надеюсь, что это поможет кому-то.

-Brandon

P.S. Для полной загрузки, вот файлы заголовков:

@interface NSDictionary (NullReplacement)

- (NSDictionary *)dictionaryByReplacingNullsWithBlanks;

@end

И заголовок массива:

@interface NSArray (NullReplacement)

- (NSArray *)arrayByReplacingNullsWithBlanks;

@end

Ответ 3

Перемещение по поиску словаря для NSNull - один из способов решения этой проблемы, но я сделал несколько более ленивый подход. Вместо nil вы можете назначить пустую строку, но принцип тот же.

CPJSONDictionary.h

@interface NSDictionary (CPJSONDictionary)
- (id)jsonObjectForKey:(id)aKey;
@end

CPJSONDictionary.m

@implementation NSDictionary (CPJSONDictionary)

- (id)jsonObjectForKey:(id)aKey {
    id object = [self objectForKey:aKey];
    if ([object isKindOfClass:[NSNull class]]) {
        object = nil;
    }

    return object;
}

@end

Ответ 4

другая вариация:

NSDictionary * NewDictionaryReplacingNSNullWithEmptyNSString(NSDictionary * dict) {
    NSMutableDictionary * const m = [dict mutableCopy];    
    NSString * const empty = @"";
    id const nul = [NSNull null];
    NSArray * const keys = [m allKeys];
    for (NSUInteger idx = 0, count = [keys count]; idx < count; ++idx) {
        id const key = [keys objectAtIndex:idx];
        id const obj = [m objectForKey:key];
        if (nul == obj) {
            [m setObject:empty forKey:key]; 
        }
    }

    NSDictionary * result = [m copy];
    [m release];
    return result;
}

Результат такой же, как и, похоже, почти идентичен Jacob's, но требования к скорости и памяти составляют от половины до одной трети (ARC или MRC) в тестах, которые я сделал. Конечно, вы также можете использовать его как метод категории.

Ответ 5

Я протестировал решение Stakenborg. Он работает хорошо, но у него есть следующая проблема. Если ожидается, что какой-то объект будет номером, преобразование его в NSNull может быть источником ошибки. Я создал новый метод для прямого удаления записей NSNull. Таким образом, вам нужно только проверить, существует ли соответствующий ключ.

Добавить в NSDictionary+NullReplacement

- (NSDictionary *)dictionaryByRemovingNulls{
    const NSMutableDictionary *replaced = [self mutableCopy];
    const id nul = [NSNull null];

    for (NSString *key in self) {
        id object = [self objectForKey:key];
        if (object == nul) [replaced removeObjectForKey:key];

        else if ([object isKindOfClass:[NSDictionary class]]) [replaced setObject:[object dictionaryByRemovingNulls] forKey:key];
        else if ([object isKindOfClass:[NSArray class]]) [replaced setObject:[object arrayByRemovingNulls] forKey:key];
    }
    return [NSDictionary dictionaryWithDictionary:[replaced copy]];
}

И в NSArray+NullReplacement

- (NSArray *)arrayByRemovingNulls {
    NSMutableArray *replaced = [self mutableCopy];
    const id nul = [NSNull null];

    for (int idx = [replaced count]-1; idx >=0; idx--) {
        id object = [replaced objectAtIndex:idx];
        if (object == nul) [replaced removeObjectAtIndex:idx];
        else if ([object isKindOfClass:[NSDictionary class]]) [replaced replaceObjectAtIndex:idx withObject:[object dictionaryByRemovingNulls]];
        else if ([object isKindOfClass:[NSArray class]]) [replaced replaceObjectAtIndex:idx withObject:[object arrayByRemovingNulls]];
    }
    return [replaced copy];
}

Я надеюсь, что это поможет

Ответ 6

Вот мое решение:

+ (NSDictionary *)cleanNullInJsonDic:(NSDictionary *)dic
{
    if (!dic || (id)dic == [NSNull null])
    {
        return dic;
    }
    NSMutableDictionary *mulDic = [[NSMutableDictionary alloc] init];
    for (NSString *key in [dic allKeys])
    {
        NSObject *obj = dic[key];
        if (!obj || obj == [NSNull null])
        {
//            [mulDic setObject:[@"" JSONValue] forKey:key];
        }else if ([obj isKindOfClass:[NSDictionary class]])
        {
            [mulDic setObject:[self cleanNullInJsonDic:(NSDictionary *)obj] forKey:key];
        }else if ([obj isKindOfClass:[NSArray class]])
        {
            NSArray *array = [BasicObject cleanNullInJsonArray:(NSArray *)obj];
            [mulDic setObject:array forKey:key];
        }else
        {
            [mulDic setObject:obj forKey:key];
        }
    }
    return mulDic;
}


+ (NSArray *)cleanNullInJsonArray:(NSArray *)array
{
    if (!array || (id)array == [NSNull null])
    {
        return array;
    }
    NSMutableArray *mulArray = [[NSMutableArray alloc] init];
    for (NSObject *obj in array)
    {
        if (!obj || obj == [NSNull null])
        {
//            [mulArray addObject:[@"" JSONValue]];
        }else if ([obj isKindOfClass:[NSDictionary class]])
        {
            NSDictionary *dic = [self cleanNullInJsonDic:(NSDictionary *)obj];
            [mulArray addObject:dic];
        }else if ([obj isKindOfClass:[NSArray class]])
        {
            NSArray *a = [BasicObject cleanNullInJsonArray:(NSArray *)obj];
            [mulArray addObject:a];
        }else
        {
            [mulArray addObject:obj];
        }
    }
    return mulArray;
}    

Ответ 7

-(NSDictionary*)stripNulls:(NSDictionary*)dict{

    NSMutableDictionary *returnDict = [NSMutableDictionary new];
    NSArray *allKeys = [dict allKeys];
    NSArray *allValues = [dict allValues];

    for (int i=0; i<[allValues count]; i++) {
        if([allValues objectAtIndex:i] == (NSString*)[NSNull null]){
            [returnDict setValue:@"" forKey:[allKeys objectAtIndex:i]];
        }
    else
        [returnDict setValue:[allValues objectAtIndex:i] forKey:[allKeys objectAtIndex:i]];
    }

return returnDict;
}

Ответ 8

Категория на nsnull, которая возвращает nil, кажется, также имеет смысл, по крайней мере для меня. Есть несколько. Один заставляет все вызовы возвращать нуль, что, кажется, имеет смысл. Извините, нет ссылки. Я думаю, если вам нужно будет использовать nspropertylistserialization, то категория может не работать для вас.