How can I encode a nil property as an empty JSON object?
struct Foo: Encodable {
let id = 10
let bar: Bar? = nil
}
struct Bar: Encodable {
let number: Int
}
let data = try! JSONEncoder().encode(Foo())
print(String(data: data, encoding: .utf8)!)
This prints out:
"{"id":7}"
What I want is:
"{"id":7, "bar":{}}"
Not sure why you'd need this, as encoding to a form that fails decoding is not something usually done.
Nonetheless, if you find yourself needing this kind of logic in multiple places, you can extend KeyedEncodingContainer
with this kind of functionality:
extension KeyedEncodingContainer {
mutating func encodeOptional<T: Encodable>(_ value: T?, forKey key: Self.Key) throws {
if let value = value { try encode(value, forKey: key) }
else { try encode([String:String](), forKey: key) }
}
}
, and then implement the encode(to:)
method in Foo
:
struct Foo: Encodable {
let id = 10
let bar: Bar? = nil
enum CodingKeys: String, CodingKey {
case id
case bar
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(id, forKey: .id)
try container.encodeOptional(bar, forKey: .bar)
}
}
You can also extend UnkeyedDecodingContainer
, and SingleValueDecodingContainer
with similar encodeOptional
methods, if you find yourself needing to encode empty JSON objects for nil values in other kind of containers.