Replace Occurrences of Nsnull in Nested Nsdictionary

Replace occurrences of NSNull in nested NSDictionary

A small modification to the method can make it recursive:

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

@implementation NSDictionary (JRAdditions)

- (NSDictionary *) dictionaryByReplacingNullsWithStrings {
const NSMutableDictionary *replaced = [NSMutableDictionary dictionaryWithDictionary: self];
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: [(NSDictionary *) object dictionaryByReplacingNullsWithStrings] forKey: key];
}
}
return [NSDictionary dictionaryWithDictionary: replaced];
}

Note that the fast-enumeration is now on self instead of replaced

With the code above, this example:

NSMutableDictionary *dic1 = [NSMutableDictionary dictionary];
[dic1 setObject: @"string 1" forKey: @"key1.1"];
[dic1 setObject: [NSNull null] forKey: @"key1.2"];

NSMutableDictionary *dic2 = [NSMutableDictionary dictionary];
[dic2 setObject: @"string 2" forKey: @"key2.1"];
[dic2 setObject: [NSNull null] forKey: @"key2.2"];

[dic1 setObject: dic2 forKey: @"key1.3"];

NSLog(@"%@", dic1);
NSLog(@"%@", [dic1 dictionaryByReplacingNullsWithStrings]);

renders this result:

2012-09-01 08:30:16.210 Test[57731:c07] {
"key1.1" = "string 1";
"key1.2" = "<null>";
"key1.3" = {
"key2.1" = "string 2";
"key2.2" = "<null>";
};
}
2012-09-01 08:30:16.212 Test[57731:c07] {
"key1.1" = "string 1";
"key1.2" = "";
"key1.3" = {
"key2.1" = "string 2";
"key2.2" = "";
};

Replace all NSNull objects in an NSDictionary

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

How to check value null and replace it in NSDictionary

could you please check this link, I think, it will be helpful to you, thanks for this link
Replace occurrences of NSNull in nested NSDictionary

UPDATE: I modified original a bit, and use some the function of converting nsarray to nsdictionary from this link Convert NSArray to NSDictionary, cuz I don't know anything about your code, so I try to make my json string as close as possible to be the same as yours, and it's work, see the following. :)

- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
tmpDict = [[NSMutableDictionary alloc] init];

NSMutableDictionary *testDict = [[NSMutableDictionary alloc] init];
[testDict setValue:[NSNull null] forKey:@"NullValue"];
[testDict setValue:@"test" forKey:@"UnNull"];
subArr = [[NSMutableArray alloc] initWithObjects:testDict, testDict, nil];

[tmpDict setValue:[NSNull null] forKey:@"NullHere"];
[tmpDict setValue:@"wear" forKey:@"NotNull"];
[tmpDict setObject:subArr forKey:@"Array"];

myArr = [[NSMutableArray alloc] initWithObjects:tmpDict, tmpDict, nil];
NSLog(@"struct: %@", myArr);

[self dictionaryByReplacingNullsWithStrings];
}

- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}

- (void) dictionaryByReplacingNullsWithStrings {
const NSMutableDictionary *replaced = [NSMutableDictionary dictionaryWithDictionary: [self indexKeyedDictionaryFromArray:myArr]];
const id nul = [NSNull null];
const NSString *blank = @"";

for (NSString *key in [replaced allKeys]) {
const id object = [replaced objectForKey: key];
if (object == nul) {
[replaced setObject: blank forKey: key];
}
else if ([object isKindOfClass: [NSDictionary class]]) {
NSLog(@"found null inside and key is %@", key);
[replaced setObject:[self replaceNullInNested:object] forKey:key];
}

}
NSLog(@"replaced: %@", replaced);
}

- (NSMutableDictionary *)replaceNullInNested:(NSDictionary *)targetDict
{
//make it to be NSMutableDictionary in case that it is nsdictionary
NSMutableDictionary *m = [targetDict mutableCopy];
NSMutableDictionary *replaced = [NSMutableDictionary dictionaryWithDictionary: m];
const id nul = [NSNull null];
const NSString *blank = @"";

for (NSString *key in [replaced allKeys]) {
const id object = [replaced objectForKey: key];
if (object == nul) {
[replaced setObject: blank forKey: key];
}
else if ([object isKindOfClass: [NSArray class]]) {
NSLog(@"found null inside and key is %@", key);
//make it to be able to set value by create a new one
NSMutableArray *a = [object mutableCopy];
for (int i =0; i< [a count]; i++) {

for (NSString *subKey in [[a objectAtIndex:i] allKeys]) {
// NSLog(@"key: %@", subKey);
// NSLog(@"value: %@", [[object objectAtIndex:i] valueForKey:subKey]);
if ([[object objectAtIndex:i] valueForKey:subKey] == nul) {
[[object objectAtIndex:i] setValue:blank forKey:subKey];
}
}

}
//replace the updated one with old one
[replaced setObject:a forKey:key];

}

}

return replaced;
}

- (NSDictionary *) indexKeyedDictionaryFromArray:(NSArray *)array
{
id objectInstance;
NSUInteger indexKey = 0;

NSMutableDictionary *mutableDictionary = [[NSMutableDictionary alloc] init];
for (objectInstance in array)
[mutableDictionary setObject:objectInstance forKey:[NSNumber numberWithUnsignedInt:indexKey++]];

return (NSDictionary *)mutableDictionary;
}

from the code above, this is the result:

replacenullvalue[1590:11303] struct: (
{
Array = (
{
NullValue = "<null>";
UnNull = test;
},
{
NullValue = "<null>";
UnNull = test;
}
);
NotNull = wear;
NullHere = "<null>";
},
{
Array = (
{
NullValue = "<null>";
UnNull = test;
},
{
NullValue = "<null>";
UnNull = test;
}
);
NotNull = wear;
NullHere = "<null>";
}
)
2012-12-16 15:16:22.790 replacenullvalue[1590:11303] found null inside and key is 0
2012-12-16 15:16:22.790 replacenullvalue[1590:11303] found null inside and key is Array
2012-12-16 15:16:22.791 replacenullvalue[1590:11303] found null inside and key is 1
2012-12-16 15:16:22.791 replacenullvalue[1590:11303] found null inside and key is Array
2012-12-16 15:16:22.792 replacenullvalue[1590:11303] replaced: {
0 = {
Array = (
{
NullValue = "";
UnNull = test;
},
{
NullValue = "";
UnNull = test;
}
);
NotNull = wear;
NullHere = "";
};
1 = {
Array = (
{
NullValue = "";
UnNull = test;
},
{
NullValue = "";
UnNull = test;
}
);
NotNull = wear;
NullHere = "";
};
}

hope it help you :).

How to handle NSNull values

NSNull objects typically crop up with people reading JSON files containing null values.

In that case, there is a chance that the server that supplied the null value thinks you should do something different than with no value. For example, if you get a dictionary and there might be a string stored under some key, you might get a string with non-zero length, you might get an empty string because the server sent you an empty string, you might get nothing because the server sent you nothing, or you might get [NSNull null] because the server sent you a null value. Up to you to decide if the empty string, nothing, and [NSNull null] need to be treated differently or not.

By the way: I have always used some extensions to the NSDictionary class, for example - (NSString*)stringForKey, which will return either an NSString or nil, 100% guaranteed. If you do that, all your error checking is in one method. And you can do things like converting NSNumber to NSString, or NSNull to nil, or NSDictionary etc. to nil, and never worry about it again. Of course you need to check if it is appropriate.

Comparing two NSDictionaries and deleting if keys don't match

this code will give you keys that changed:

NOTE: as the lookup of keys is basically jumping into a hashmap (an o1 op), you dont have to worry about the 2nd array walk you talk about

#import <Foundation/Foundation.h>

@interface NSDictionary (changedKeys)
- (NSArray*)changedKeysIn:(NSDictionary*)d;
@end

@implementation NSDictionary (changedKeys)
- (NSArray*)changedKeysIn:(NSDictionary*)d {
NSMutableArray *changedKs = [NSMutableArray array];
for(id k in self) {
if(![[self objectForKey:k] isEqual:[d objectForKey:k]])
[changedKs addObject:k];
}
return changedKs;
}
@end

int main(int argc, char *argv[]) {
@autoreleasepool {
NSDictionary *d1 = @{@"1":@"value",@"2":@"value",@"3":@"value",@"4":@"value"};
NSDictionary *d2 = @{@"1":@"value",@"2":@"newvalue",@"3":@"value"};

NSArray *ks = [d1 changedKeysIn:d2];
NSLog(@"%@", ks);

}

return 0;
}

Edit: self.allKeys changed to just self -- a dictionary can be enumerated already



Related Topics



Leave a reply



Submit