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.
You use the JSONSerialization class to convert JSON to Foundation objects and convert Foundation objects to JSON. To convert a Foundation object to JSON, the object must have the following properties: The top level object is an NSArray or NSDictionary , unless you set the fragmentsAllowed option.
Reading OptionsSpecifies that leaf strings in the JSON object graph are mutable. Specifies that the parser allows top-level objects that aren't arrays or dictionaries. Specifies that reading serialized JSON data supports the JSON5 syntax.
Swift version: 5.6. If you want to parse JSON by hand rather than using Codable , iOS has a built-in alternative called JSONSerialization and it can convert a JSON string into a collection of dictionaries, arrays, strings and numbers in just a few lines of code.
mutableContainers ( NSJSONReadingMutableContainers ): 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 .
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 NSArray
→ NSMutableArray
and NSDictionary
→ NSMutableDictionary
.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+).
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 NSArray
s or NSDictionary
s contained in the result must be NSMutableArray
s or NSMutableDictionary
s. 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 NSString
s contained in the result must be NSMutableString
s. 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.
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)
}
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. If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With