Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JSONSerialization with optionals in Swift 3

Tags:

json

swift

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?

like image 482
davedavedave Avatar asked Feb 06 '23 22:02

davedavedave


1 Answers

Update: As of Swift 3.0.1/Xcode 8.1 beta 2, optionals are bridged to NSNull instances automatically, see

  • SE-0140 – Warn when Optional converts to Any, and bridge Optional As Its Payload Or NSNull

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"]
like image 61
Martin R Avatar answered Feb 08 '23 13:02

Martin R