What do JSONSerialization options do and how do they change jsonResult?

17,295

Solution 1

Short answer for the first two options:

Ignore them in Swift!

In Swift you can make objects mutable just with the var keyword.

In Objective-C on the other hand you need

  • NSJSONReadingMutableContainers to make the nested collection types mutable NSArrayNSMutableArray and NSDictionaryNSMutableDictionary.
  • NSJSONReadingMutableLeaves to make the value strings mutable → NSMutableString.

In both Objective-C and Swift if you are only reading the JSON you don't need mutability at all.

The third option NSJSONReadingAllowFragments is important if the root object of the received JSON is not an array and not a dictionary.
If it is an array or dictionary you can omit that option, too.

The pair of empty brackets [] represents No options (the options parameter can be omitted in Swift 3+).

Solution 2

You'd better know how JSON values are imported into iOS world:

 JSON array ->  NSArray
 JSON object -> NSDictionary
 JSON number -> NSNumber
 JSON string -> NSString
 JSON true   -> NSNumber
 JSON false  -> NSNumber
 JSON null   -> NSNull

(You'd better also check the RFCs of JSON. RFC-4627, RFC-7159)

Then re-check the all options again:

mutableContainers (NSJSONReadingMutableContainers):

Guarantees the NSArrays or NSDictionarys contained in the result must be NSMutableArrays or NSMutableDictionarys. Someone says in older iOSs JSONSerialization (NSJSONSerialization) returned mutable objects without specifying mutableContainers, but depending on it is not recommended, and actually you can find someones reporting such code does not work in iOS 10.

In Swift, mutability is represented by var and let, so you have no need to use this option in Swifty codes. Only needed when you cast some parts of the deserialized result to NSMutableArray or NSMutableDictionary. I strongly recommend to rewrite such codes in a more Swifty manner.

mutableLeaves (NSJSONReadingMutableLeaves):

Guarantees the NSStrings contained in the result must be NSMutableStrings. Rarely used even in old Objective-C codes, ignore it.

allowFragments (NSJSONReadingAllowFragments):

In old RFC (RFC-4627), only array and object were valid as the outermost component of JSON. If you expect array or object (NSDictionary) from the server, NOT specifying this option would help you to find the invalid returned value from the server a little bit sooner.

Seeing the difference in codes:

Assume data1 is a valid UTF-8 representation of the following JSON:

[{"name": "aaa", "value": 123}, {"name": "bbb", "value": 456}]

And the code:

do {
    let result = try JSONSerialization.jsonObject(with: data1)
    let resultArray = result as! NSMutableArray //->This may cause your app crash
    //->Could not cast value of type '__NSArrayI' (0x105e79c08) to 'NSMutableArray' (0x105e79cd0).
    print(resultArray)
} catch {
    print(error)
}
 
do {
    let result = try JSONSerialization.jsonObject(with: data1, options: [.mutableContainers])
    let resultArray = result as! NSMutableArray //->This should always work
    print(resultArray) //->shows output...
} catch {
    print(error)
}

And data2:

-1

And the comparison for it:

do {
    let result = try JSONSerialization.jsonObject(with: data2)
    print(result)
} catch {
    print(error) //->Error Domain=NSCocoaErrorDomain Code=3840 "JSON text did not start with array or object and option to allow fragments not set." UserInfo={NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.}
}

do {
    let result = try JSONSerialization.jsonObject(with: data2, options: [.allowFragments])
    print(result) //-> -1
} catch {
    print(error)
}

Solution 3

Options: [] is an empty array returns nothing.

Whereas Options: [] can also be amend with:

  • NSJSONWritingOptions: for writing JSON data like.

    • NSJSONWritingOptions.NSJSONWritingPrettyPrinted: Specifies that the JSON data should be generated with whitespace designed to make the output more readable. If this option is not set, the most compact possible JSON representation is generated.
  • NSJSONReadingOptions: used when creating Foundation objects from JSON data.

    • NSJSONReadingOptions.MutableContainers: Specifies that arrays and dictionaries are created as mutable objects.
    • .mutableLeaves: Specifies that leaf strings in the JSON object graph are created as instances of NSMutableString.
    • .allowFragments: Specifies that the parser should allow top-level objects that are not an instance of NSArray or NSDictionary.
Share:
17,295
0ndre_
Author by

0ndre_

Swift, php/mysql => iOS apps :3 and of course PYTHON!

Updated on June 06, 2022

Comments

  • 0ndre_
    0ndre_ almost 2 years

    I am using JSONSerialization quite often in my project. Here is an example of my JSONSerialization code:

    let json = try JSONSerialization.jsonObject(with: data!, options: []) as? [String: Any] 
    

    Note: Options are missing for purpose and I normally have them in my project.

    My problem is that I am not pretty sure what do these options: [] do?

    What I have found about options:

    NSJSONReadingMutableContainers:

    Specifies that arrays and dictionaries are created as mutable objects.

    NSJSONReadingMutableLeaves:

    Specifies that leaf strings in the JSON object graph are created as instances of NSMutableString.

    NSJSONReadingAllowFragments:

    Specifies that the parser should allow top-level objects that are not an instance of NSArray or NSDictionary.

    Note2: I found those definitions on : https://developer.apple.com/reference/foundation/nsjsonreadingoptions

    My question is: Can someone please explain me differences between those options , what should I use them for and if you could show me some code example of those options it would be perfect :).

    Any help appreciated.

    Thanks.