简体   繁体   English

如何从 NSDictionary 中删除空值

[英]How to remove a null value from NSDictionary

I have a JSON Feed:我有一个 JSON 提要:

{
    "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>" .问题是"<null>" I cannot figure out how to remove it from the NSDictionary before saving it to NSUserDefaults.在将它保存到 NSUserDefaults 之前,我无法弄清楚如何从 NSDictionary 中删除它。

Another variation, without (explicit) loop:另一个变体,没有(显式)循环:

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

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.之后, prunedDictionary应该包含原始字典中的所有非空项目。

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

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 :文件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 :文件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];
}

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'.如果您不使用 ARC,则需要添加一些对“release”的调用。

Update:更新:

If you don't know the name of the key(s) with the "<null>" objects, then you have to iterate:如果您不知道带有"<null>"对象的键的名称,则必须迭代:

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.为了定位"<null>"值,我使用了字符串比较,因为"<null>"是样本中的字符串。 But I'm not sure if this is really the case.但我不确定这是否真的如此。

I belive this is the most resource saving way我相信这是最节省资源的方式

// category implementation on NSDictionary // 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;
}

I have created a category for NSJSOn serialisation class.我为 NSJSOn 序列化类创建了一个类别。

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;

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

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

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当结果在数组或字典中时,以下代码是可以的,您可以通过编辑代码将返回的结果更改为 nil 或空字符串

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

resulting in:导致:

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

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

Swift 3.0/4.0 Solution Swift 3.0/4.0解决方案

Following is the solution, when JSON have sub-dictionaries .以下是解决方案,当JSONsub-dictionaries This will go-through all the dictionaries , sub -dictionaries of JSON and remove NULL(NSNull) key-value pair from the JSON .这将大大-通过所有的dictionaries ,分-dictionariesJSON和删除NULL(NSNull) key-value从对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>
    }
 }

Add this 3 methods in your view controller, and call this method like this way在你的视图控制器中添加这 3 个方法,并像这样调用这个方法

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

Modify @sinh99 answer.修改@sinh99 答案。 Use a new NSMutableDictionary to collection no-null values and sub-dictionary values.使用新的 NSMutableDictionary 来收集非空值和子字典值。


- (NSMutableDictionary *)recursiveRemoveNullValues:(NSDictionary *)dictionary {

    NSMutableDictionary *mDictionary = [NSMutableDictionary new];
    for (NSString *key in [dictionary allKeys]) {
        id nullString = [dictionary objectForKey:key];

        if ([nullString isKindOfClass:[NSDictionary class]]) {
            NSMutableDictionary *mDictionary_sub = [self recursiveRemoveNullValues:(NSDictionary*)nullString];
            [mDictionary setObject:mDictionary_sub forKey:key];
        } else {

            if ((NSString*)nullString == (id)[NSNull null]) {
                [mDictionary setValue:@"" forKey:key];
            } else {
                [mDictionary setValue:nullString forKey:key];
            }
        }
    }

    return mDictionary;
}


Swift - Nested NSNull supported Swift - 支持嵌套NSNull

First of all, we use Dictionary in Swift instead of NSDictionary .首先,我们在 Swift 中使用Dictionary而不是NSDictionary

To remove any NSNull appearance in any nested level (including arrays and dictionaries ), try this:要删除任何嵌套级别(包括数组字典)中的任何NSNull外观,请尝试以下操作:

extension Dictionary where Key == String {
    func removeNullsFromDictionary() -> Self {
        var destination = Self()
        for key in self.keys {
            guard !(self[key] is NSNull) else { destination[key] = nil; continue }
            guard !(self[key] is Self) else { destination[key] = (self[key] as! Self).removeNullsFromDictionary() as? Value; continue }
            guard self[key] is [Value] else { destination[key] = self[key]; continue }

            let orgArray = self[key] as! [Value]
            var destArray: [Value] = []
            for item in orgArray {
                guard let this = item as? Self else { destArray.append(item); continue }
                destArray.append(this.removeNullsFromDictionary() as! Value)
            }
            destination[key] = destArray as? Value
        }
        return destination
    }
}

Note that the key of the dictionary should be String注意字典的key应该是String

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM