I am using JSONSerialization
quite often in my project.
Here is an example of my JSONSerialization
code:
let json = try JSONSeriali
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+).
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. 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)
}