10

Specifically, this problem has come to me when I make a request with AFNeworking with JSONkit and receive a (id)JSON with several arrays and dictionaries nested.

If I don't want to modify the data, I don't have any problem:

self.myNSArray = [JSON objectForKey:@"result"];

But if I want to modify the data I must to store it in a mutable variable:

self.myNSMutableArray = [[JSON objectForKey:@"result"] mutableCopy];

The last one doesn't convert nested arrays or dictionaries to mutable data; it works only for first level.

The only way that I have found is on this link recursive mutable objects; but I don't know if there is a best way to resolve this kind of problem.

Thanks in advance.

martinezdelariva
  • 5,011
  • 2
  • 25
  • 30

3 Answers3

11

You could use the CoreFoundation function CFPropertyListCreateDeepCopy with the mutability option kCFPropertyListMutableContainersAndLeaves:

NSArray *immutableArray = [JSON objectForKey:@"result"];
self.myMutableArray = [(NSMutableArray *)CFPropertyListCreateDeepCopy(NULL, immutableArray, kCFPropertyListMutableContainersAndLeaves) autorelease];
omz
  • 53,243
  • 5
  • 129
  • 141
  • 2
    The ARC equivalent seems to be `CFBridgingRelease(CFPropertyListCreateDeepCopy(NULL, (__bridge CFPropertyListRef)(immutableArray), kCFPropertyListMutableContainersAndLeaves));` – brainjam Oct 24 '12 at 18:03
  • 1
    @omz Should this work for dictionaries, do you know? Can't seem to get it to convert. – Dom Vinyard Nov 24 '12 at 01:52
  • It should. Please post a separate question with more details. – omz Nov 24 '12 at 02:12
  • This [seems to return a `nil` value](http://stackoverflow.com/q/34219638/937891) if the immutableArray has a `NULL` somewhere, do you happen to know of a workaround in those cases? – S P Dec 11 '15 at 09:46
  • 1
    @Sathvik Property lists simply don't support `NSNull` values. If you want to serialize collections that contain them, consider using `NSJSONSerialization` or `NSKeyedArchiver`. – omz Dec 12 '15 at 12:26
5

On ARC:

CFBridgingRelease(CFPropertyListCreateDeepCopy(NULL, (__bridge CFPropertyListRef)(immutableArray), kCFPropertyListMutableContainersAndLeaves))

really worked. Thanks brainjam.

Hoang Nguyen Huu
  • 1,202
  • 17
  • 17
0

Make sure you are taking care of null values in response string, otherwise it will return you nil which causes to horrible results.

(For Eg. Try mutataing response from http://www.json-generator.com/api/json/get/bQVoMjeJOW?indent=1)

Just place below line when converting API response to JSON Object.

responseString=[responseString stringByReplacingOccurrencesOfString:@"\":null" withString:@"\":\"\""];//To Handle Null Characters

//Search for below line in your parsing library and paste above code
data = [responseString dataUsingEncoding:NSUTF8StringEncoding];

So there will be no null characters in your JSON object, hence no issue with using CFPropertyListCreateDeepCopy.

Cheers!!

Loquatious
  • 1,791
  • 12
  • 21