替换 NSDictionary 中的所有 NSNull 对象

发布于 2024-12-14 19:32:10 字数 210 浏览 1 评论 0原文

我很好奇,我目前有一个 NSDictionary ,在 json-framework 的帮助下,其中一些值被设置为 NSNull 对象。

目的是删除所有 NSNull 值并将其替换为空字符串。

我确信有人在某处做过这件事?毫无疑问,这可能是一个四衬里,而且很简单,我只是太累了,无法自己解决这个问题。

I'm curious, I currently have an NSDictionary where some values are set to an NSNull object thanks to the help of json-framework.

The aim is to strip all NSNull values and replace it with an empty string.

I'm sure someone has done this somewhere? No doubt it is probably a four liner and is simple, I am just far too burnt out to figure this out on my own.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

梦一生花开无言 2024-12-21 19:32:12

这是我的解决方案:

+ (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;
}    

Here is my solution:

+ (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;
}    
风月客 2024-12-21 19:32:12
-(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;
}
-(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;
}
污味仙女 2024-12-21 19:32:12

nsnull 上返回 nil 的类别似乎也有意义,至少对我来说。那里有一些。让所有调用都返回 nil,这似乎是有道理的。抱歉没有链接。我想如果您稍后需要使用 nspropertylistserialization,该类别可能不适合您。

A category on nsnull that returns nil seems to also sense, at least to me. There are a few out there. One makes all calls return nil which seems to make sense. Sorry no link. I guess if you need to later use nspropertylistserialization the category might not work for you.

定格我的天空 2024-12-21 19:32:11

我对 Jacob 的原始答案进行了一些更改,以将其扩展为处理存储在原始字典中的字典和数组。

#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] 实例。

PS 为了完整起见,这里是头文件:

@interface NSDictionary (NullReplacement)

- (NSDictionary *)dictionaryByReplacingNullsWithBlanks;

@end

和数组头:

@interface NSArray (NullReplacement)

- (NSArray *)arrayByReplacingNullsWithBlanks;

@end

I've made a few changes to Jacob's original answer to extend it to handle dictionaries and arrays stored within the original dictionary.

#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

And there's also an array category of course:

#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

With this, you can take any array or dictionary and recursively wipe out all the [NSNull null] instances.

P.S. For completion's sake, here are the header files:

@interface NSDictionary (NullReplacement)

- (NSDictionary *)dictionaryByReplacingNullsWithBlanks;

@end

And the array header:

@interface NSArray (NullReplacement)

- (NSArray *)arrayByReplacingNullsWithBlanks;

@end
宫墨修音 2024-12-21 19:32:11

非常简单:

@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];

Really simple:

@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

Usage:

NSDictionary *someDictThatHasNulls = ...;
NSDictionary *replacedDict = [someDictThatHasNulls dictionaryByReplacingNullsWithStrings];
提赋 2024-12-21 19:32:11

滚动字典寻找 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

Rolling through the dictionary hunting for NSNull is one way to tackle the problem, but I took a slightly lazier approach. Instead of nil you could assign an empty string, but the principle is the same.

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
空宴 2024-12-21 19:32:11

我已经测试了 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];
}

I have tested Stakenborg solution. It works well, but it has following problem. If some object is expected to be number, for instance, converting it to NSNull can be a source of error.
I have create a new method to directly remove the NSNull entries. This way you only have to check that correspondant key exists.

Add in 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]];
}

And in 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];
}
偏爱你一生 2024-12-21 19:32:11

另一种变体:

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 的结果相同,并且看起来与 Jacob 的几乎相同,但在我所做的测试中,速度和内存要求是二分之一到三分之一(ARC 或 MRC)。当然,您也可以将其用作类别方法。

another variation:

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;
}

The result is the same as, and it appears pretty much identical to Jacob's, but the speed and memory requirements are one half to one third (ARC or MRC) in the tests I made. Of course, you could also use it as a category method as well.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文