How to remove a null value from NSDictionary

2019-02-03 05:42发布

问题:

I have a JSON Feed:

{
            "count1" = 2;
            "count2" = 2;
            idval = 40;
            level = "<null>";
            "logo_url" = "/assets/logos/default_logo_medium.png";
            name = "Golf Club";
            "role_in_club" = Admin;
}

The problem is the "<null>" that I cannot figure out how to remove from the NSDictionary before saving it to NSUserDefaults.

Please help me solve this issue. Thankyou!

回答1:

Iterate through the dictionary and look for any null entries and remove them.

NSMutableDictionary *prunedDictionary = [NSMutableDictionary dictionary];
for (NSString * key in [yourDictionary allKeys])
{
    if (![[yourDictionary objectForKey:key] isKindOfClass:[NSNull class]])
        [prunedDictionary setObject:[yourDictionary objectForKey:key] forKey:key];
}

After that, prunedDictionary should have all non-null items in the original dictionary.



回答2:

Another variation, without (explicit) loop:

NSMutableDictionary *dict = [yourDictionary mutableCopy];
NSArray *keysForNullValues = [dict allKeysForObject:[NSNull null]];
[dict removeObjectsForKeys:keysForNullValues];


回答3:

Use this for remove null from dictionary

- (NSMutableDictionary *)recursive:(NSMutableDictionary *)dictionary {
for (NSString *key in [dictionary allKeys]) {    
    id nullString = [dictionary objectForKey:key];   
    if ([nullString isKindOfClass:[NSDictionary class]]) {
        [self recursive:(NSMutableDictionary*)nullString];
    } else {
        if ((NSString*)nullString == (id)[NSNull null])
            [dictionary setValue:@"" forKey:key];
    }
}
return dictionary;
}


回答4:

Here is my category-based recursive solution for dictionaries containing dictionaries and arrays which values can also be dictionaries and arrays:

File NSDictionary+Dario.m:

#import "NSArray+Dario.h"

@implementation NSDictionary (Dario)

- (NSDictionary *) dictionaryByReplacingNullsWithEmptyStrings {

    const NSMutableDictionary *replaced = [NSMutableDictionary new];
    const id nul = [NSNull null];
    const NSString *blank = @"";

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

@end

File NSArray+Dario.m:

#import "NSDictionary+Dario.h"

@implementation NSArray (Dario)

- (NSArray *) arrayByReplacingNullsWithEmptyStrings {
    const NSMutableArray *replaced = [NSMutableArray new];
    const id nul = [NSNull null];
    const NSString *blank = @"";

    for (int i=0; i<[self count]; i++) {
        const id object = [self objectAtIndex:i];

        if ([object isKindOfClass:[NSDictionary class]]) {
            [replaced setObject:[object dictionaryByReplacingNullsWithEmptyStrings] atIndexedSubscript:i];
        } else if ([object isKindOfClass:[NSArray class]]) {
            [replaced setObject:[object arrayByReplacingNullsWithEmptyStrings] atIndexedSubscript:i];
        } else if (object == nul){
            [replaced setObject:blank atIndexedSubscript:i];
        } else {
            [replaced setObject:object atIndexedSubscript:i];
        }
    }
    return [NSArray arrayWithArray:(NSArray*)replaced];
}


回答5:

To remove it, convert it into a mutable dictionary and remove the object for key "level";

NSDictionary* dict = ....;  // this is the dictionary to modify
NSMutableDictionary* mutableDict = [dict mutableCopy];
[mutableDict removeObjectForKey:@"level"];
dict = [mutableDict copy];

If you don't use ARC, you'll need to add some calls to 'release'.

Update:

If you don't know the name of the key(s) with the "<null>" objects, then you have to iterate:

NSDictionary* dict = ....;  // this is the dictionary to modify
NSMutableDictionary* mutableDict = [dict mutableCopy];
for (id key in dict) {
    id value = [dict objectForKey: key];
    if ([@"<null>" isEqual: value]) {
        [mutableDict removeObjectForKey:key];
    }
}
dict = [mutableDict copy];

To locate the "<null>" values, I'm using a string comparison since "<null>" is a string in your sample. But I'm not sure if this is really the case.



回答6:

I belive this is the most resource saving way

// category implementation on NSDictionary

- (NSDictionary *)dictionaryByRemovingNullValues {

    NSMutableDictionary * d;
    for (NSString * key in self) {

        if (self[key] == [NSNull null]) {
            if (d == nil) {
                d = [NSMutableDictionary dictionaryWithDictionary:self];
            }
            [d removeObjectForKey:key];
        }

    }

    if (d == nil) {
        return self;
    }

    return d;
}


回答7:

I have created a category for NSJSOn serialisation class.

Create a category and import class to use its methods...

// Mutable containers are required to remove nulls.
if (replacingNulls)
{
    // Force add NSJSONReadingMutableContainers since the null removal depends on it.
    opt = opt || NSJSONReadingMutableContainers;
}

id JSONObject = [self JSONObjectWithData:data options:opt error:error];

if ((error && *error) || !replacingNulls)
{
    return JSONObject;
}

[JSONObject recursivelyReplaceNullsIgnoringArrays:ignoreArrays withString:replaceString];
return JSONObject;


回答8:

I tried the solution for your question and i got it

NSDictionary *dict = [[NSDictionary alloc]initWithObjectsAndKeys:@"2",@"count1",@"2",@"count2",@"40",@"idval",@"<null>",@"level",@"/assets/logos/default_logo_medium.png",@"logo_url",@"Golf Club",@"name",@"role_in_club",@"Admin", nil];
NSMutableDictionary *mutableDict = [dict mutableCopy];
for (NSString *key in [dict allKeys]) {
    if ([dict[key] isEqual:[NSNull null]]) {
        mutableDict[key] = @""; 
    }
    if([dict[key] isEqualToString:@"<null>"])
    {
        mutableDict[key] = @"";
    }
}
dict = [mutableDict copy];
NSLog(@"The dict is - %@",dict);

Finally the answer is

The dict is - {
Admin = "role_in_club";
count1 = 2;
count2 = 2;
idval = 40;
level = "";
"logo_url" = "/assets/logos/default_logo_medium.png";
name = "Golf Club";
}


回答9:

I am doing in this way.

NSMutableDictionary *prunedDict = [NSMutableDictionary dictionary];
[self enumerateKeysAndObjectsUsingBlock:^(NSString *key, id obj, BOOL *stop) {
  if (![obj isKindOfClass:[NSNull class]]) {
    prunedDict[key] = obj;
  }
}];


回答10:

the following code is ok when the result is in array or dictionary , you can change the result returned to nil or empty string by editing the code

the function is recursive , so can parse array in dictionary .

-(id)changeNull:(id)sender{

        id newObj;

        if ([sender isKindOfClass:[NSArray class]]){

            NSMutableArray *newArray = [[NSMutableArray alloc] init];


            for (id item in sender){

                [newArray addObject:[self changeNull:item]];

            }

            newObj = newArray;
        }

        else if ([sender isKindOfClass:[NSDictionary class]]){

            NSMutableDictionary *newDict = [[NSMutableDictionary alloc] init];

            for (NSString *key in sender){

                NSDictionary *oldDict = (NSDictionary*)sender;


                id item = oldDict[key];

                if (![item isKindOfClass:[NSDictionary class]] && ![item isKindOfClass:[NSArray class]]){

                    if ([item isEqual:[NSNull null]]){
                        item = @"";

                    }

                    [newDict setValue:item forKey:key];

                }
                else{

                    [newDict setValue:[self changeNull:item] forKey:key];

                }
            }
            newObj = newDict;
        }

        return newObj;
    }

jsonresult ( { Description = ""; Id = 1; Name = High; }, { Description = ""; Id = 2; Name = Medium; }, { Description = ""; Id = 3; Name = Low; } )

change null ( { Description = ""; Id = 1; Name = High; }, { Description = ""; Id = 2; Name = Medium; }, { Description = ""; Id = 3; Name = Low; } )



回答11:

Swift 3.0/4.0 Solution

Following is the solution, when JSON have sub-dictionaries. This will go-through all the dictionaries, sub-dictionaries of JSON and remove NULL(NSNull) key-value pair from the JSON.

extension Dictionary {

    func removeNull() -> Dictionary {
        let mainDict = NSMutableDictionary.init(dictionary: self)
        for _dict in mainDict {
            if _dict.value is NSNull {
                mainDict.removeObject(forKey: _dict.key)
            }
            if _dict.value is NSDictionary {
                let test1 = (_dict.value as! NSDictionary).filter({ $0.value is NSNull }).map({ $0 })
                let mutableDict = NSMutableDictionary.init(dictionary: _dict.value as! NSDictionary)
                for test in test1 {
                    mutableDict.removeObject(forKey: test.key)
                }
                mainDict.removeObject(forKey: _dict.key)
                mainDict.setValue(mutableDict, forKey: _dict.key as? String ?? "")
            }
            if _dict.value is NSArray {
                let mutableArray = NSMutableArray.init(object: _dict.value)
                for (index,element) in mutableArray.enumerated() where element is NSDictionary {
                    let test1 = (element as! NSDictionary).filter({ $0.value is NSNull }).map({ $0 })
                    let mutableDict = NSMutableDictionary.init(dictionary: element as! NSDictionary)
                    for test in test1 {
                        mutableDict.removeObject(forKey: test.key)
                    }
                    mutableArray.replaceObject(at: index, with: mutableDict)
                }
                mainDict.removeObject(forKey: _dict.key)
                mainDict.setValue(mutableArray, forKey: _dict.key as? String ?? "")
            }
        }
        return mainDict as! Dictionary<Key, Value>
    }
 }


回答12:

Add this 3 methods in your view controller, and call this method like this way

NSDictionary *dictSLoginData = [self removeNull:[result valueForKey:@"data"]];

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

    NSMutableDictionary *replaced = [NSMutableDictionary dictionaryWithDictionary: dict];

    const id nul = [NSNull null];
    const NSString *blank = @"";

    for (NSString *key in [dict allKeys]) {

        const id object = [dict objectForKey: key];
        if (object == nul) {
            [replaced setObject: blank forKey: key];
        } else if([object isKindOfClass: [NSDictionary class]]) {
            [replaced setObject: [self replaceNull:object] forKey: key];
        } else if([object isKindOfClass: [NSArray class]]) {
            [replaced setObject: [self replaceNullArray:object] forKey: key];
        }
    }
    return [NSDictionary dictionaryWithDictionary: replaced];
}

- (NSArray *)replaceNullArray:(NSArray *)array {

    const id nul = [NSNull null];
    const NSString *blank = @"";

    NSMutableArray *replaced = [NSMutableArray arrayWithArray:array];

    for (int i=0; i < [array count]; i++) {
        const id object = [array objectAtIndex:i];
        if (object == nul) {
            [replaced replaceObjectAtIndex:i withObject:blank];
        } else if([object isKindOfClass: [NSDictionary class]]) {
            [replaced replaceObjectAtIndex:i withObject:[self replaceNull:object]];
        } else if([object isKindOfClass: [NSArray class]]) {
            [replaced replaceObjectAtIndex:i withObject:[self replaceNullArray:object]];
        }
    }
    return replaced;
}

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

    const id nul = [NSNull null];
    const NSString *blank = @"";

    NSMutableDictionary *replaced = [NSMutableDictionary dictionaryWithDictionary: dict];

    for (NSString *key in [dict allKeys]) {
        const id object = [dict objectForKey: key];
        if (object == nul) {
            [replaced setObject: blank forKey: key];
        } else if ([object isKindOfClass: [NSDictionary class]]) {
            [replaced setObject: [self replaceNull:object] forKey: key];
        } else if([object isKindOfClass: [NSArray class]]) {
            [replaced setObject: [self replaceNullArray:object] forKey: key];
        }
    }
    return replaced;
}