I have a Codable object that I need to convert to Dictionary so I first encode it to convert it to Data and then use JSONSerialization to convert that Data to Any and then use as? [String: Any] to get the dictionary.
The conversion is successful but due to use of JSONSerialisation, Bool types are being converted to NSNumber but I want to retain the Bool value inside the Dictionary
import Foundation
struct Employee: Codable {
let employeeID: Int?
let meta: Meta?
}
struct Meta: Codable {
let demo: Bool?
}
let employeeObject = Employee(employeeID: 1, meta: Meta(demo: true))
do {
let encodedObject = try JSONEncoder().encode(employeeObject)
let dictionary = try JSONSerialization.jsonObject(with: encodedObject, options: .fragmentsAllowed) as? [String: Any]
print(dictionary ?? [:])
} catch {
print(error)
}
OUTPUT
["meta": {
demo = 1; }, "employeeID": 1]
demo property is being converted to NSNumber but I want to retain the Bool value
Well, that is how JSONSerialization works — but this scenario is a hack anyways.
You could try to do the translation with reflection (Mirror) instead.
Right. Due to its Objective-C heritage, it can’t return JSON Boolean values as Swift Bool values because those are value types, not objects.
What you’ll find, however, is that it does use CFBoolean for JSON Booleans, so you can detect whether the original was a Boolean or a number by testing against kCFBooleanTrue and kCFBooleanFalse. Consider:
// One of these 1’s is not like other…
let m = dictionary!["meta"]! as! [String:Any]
let d = m["demo"]! as! NSNumber
print(d) // 1
print(d === kCFBooleanTrue) // true
print(d === kCFBooleanFalse) // false
let e = dictionary!["employeeID"]! as! NSNumber
print(e) // 1
print(e === kCFBooleanTrue) // false
print(e === kCFBooleanFalse) // false