In Swift 3, JSONSerialization
of arrays with optional values fails.This worked in Swift 2 (yielding null as the JSON value of nil
optionals as would be expected).
Edit: It didn't, but leaving it here as this was my incorrect belief when asking the question.
Swift 2:
let a: [String!] = ["a","b","c"]
let b: [String] = ["a","b","c"]
let s: String! = "a"
let c = ["a",s]
NSJSONSerialization.isValidJSONObject(a) //true
NSJSONSerialization.isValidJSONObject(b) //true
NSJSONSerialization.isValidJSONObject(c) //true
Swift 3:
let a: [String?] = ["a","b","c"]
let b: [String] = ["a","b","c"]
let s: String! = "a"
let c = ["a",s]
JSONSerialization.isValidJSONObject(a) //false
JSONSerialization.isValidJSONObject(b) //true
JSONSerialization.isValidJSONObject(c) //false
Is this an intended change?
It seems quite error prone as any arrays or dictionaries constructed with an implicit type now potentially are not valid for JSON (even if they do not actually contain any nil values).
Additionally, how can null values then be specified?
Update: As of Swift 3.0.1/Xcode 8.1 beta 2, optionals
are bridged to NSNull
instances automatically, see
and the Xcode 8.1 beta release notes.
Example:
let array: [String?] = [ "a", nil, "c"]
let jsonData = try! JSONSerialization.data(withJSONObject: array)
print(String(data: jsonData, encoding: .utf8)!)
// ["a",null,"c"]
Previous answer for Swift 2 and 3.0: Only NSNull()
is serialized to JSON null, not optionals
(independent of the Swift version).
An array of optionals could be transformed like this:
let a: [String?] = ["a", nil, "c"]
let b = a.map { $0 as Any? ?? NSNull() }
print(b) // ["a", <null>, "c"]
let d = try! JSONSerialization.data(withJSONObject: b)
print(String(data: d, encoding: .utf8)!) // ["a",null,"c"]
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