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

前端 未结 3 565
遇见更好的自我
遇见更好的自我 2020-12-05 04:35

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

let json = try JSONSeriali         


        
相关标签:
3条回答
  • 2020-12-05 05:18

    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+).

    0 讨论(0)
  • 2020-12-05 05:19

    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.
    0 讨论(0)
  • 2020-12-05 05:29

    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)
    }
    
    0 讨论(0)
提交回复
热议问题