Replace all NSNull objects in an NSDictionary

2020-01-27 01:46发布

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.

Thanks!

8条回答
甜甜的少女心
2楼-- · 2020-01-27 02:14

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
查看更多
萌系小妹纸
3楼-- · 2020-01-27 02:15

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.

查看更多
时光不老,我们不散
4楼-- · 2020-01-27 02:17
-(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;
}
查看更多
兄弟一词,经得起流年.
5楼-- · 2020-01-27 02:19

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

I hope this helps

查看更多
Deceive 欺骗
6楼-- · 2020-01-27 02:23

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;
}    
查看更多
该账号已被封号
7楼-- · 2020-01-27 02:33

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.

Hope it helps someone.

-Brandon

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
查看更多
登录 后发表回答