storing values in NSUserDefaults, from JSON serialization, causes unwanted exceptions

I’ve got an app where I use a JSON based API. As part of JSON, often values are set to “null“. This may be common:

{"data":["one","two","three"],"name":null,otherstuff:10}

Recently I’ve tried to store a misc NSDictionary hierarchy, converted from a JSON object, in NSUserDefaults. Unfortunately it causes an exception if there is null data, converted in IOS to [NSNull null]. Apparently that can’t be saved in prefs.

  • Changing MFMailComposeViewController's toolbar color
  • I'm trying to use Dynamic Buttons by a GitHub source but the do not work
  • What's the height of a UITabBar on iOS 8, iOS 9, iOS 10, and iOS 11?
  • NSData: unexpectedly found nil while unwrapping an Optional value
  • Changing manually $(AppIdentifierPrefix) property?
  • iOS OpenGL ES 2.0: Offscreen render and save the result to an UIImage
  • I was wondering if anyone has worked around this before? I tried to add some logic to remove all null values from the JSON first, with limited success, but it seems inappropriate to have to modify the data before storing it. Is there a better way to handle this?

    2 Solutions Collect From Internet About “storing values in NSUserDefaults, from JSON serialization, causes unwanted exceptions”

    You can first convert your NSDictionary to NSData, then safely store in NSUserDefaults (since NSNull conforms to NSCoding).

    //archive
    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:dictionary];
    [[NSUserDefaults standardUserDefaults] setObject:data forKey:@"key"];
    
    //unarchive
    NSData *newData = [[NSUserDefaults standardUserDefaults] objectForKey:@"key"];
    NSDictionary *newDict = [NSKeyedUnarchiver unarchiveObjectWithData:newData];
    

    Edit: Original data object was being referenced instead of newData object.

    I’ve tried some recursive solutions but they tend to be complicated and don’t handle mixed type content well. At the simplest level here is a flat example that works well if you have a predictable, flat response to clean.

    NSMutableDictionary *dictMutable = [dict mutableCopy];
    [dictMutable removeObjectsForKeys:[dict allKeysForObject:[NSNull null]]];