davedavedave
davedavedave

Reputation: 487

JSONSerialization with optionals in Swift 3

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?

Upvotes: 5

Views: 5269

Answers (1)

Martin R
Martin R

Reputation: 539915

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"]

Upvotes: 9

Related Questions