Got you. If you want this library to be a replacement for JSON support found in Foundation it needs to have both encoding and decoding (and I would advocate for having both JSONSerialiation encode / decode as well in a general purpose JSON library).
The examples there are self explanatory (or so I thought):
Decoder: dontOverrideFieldsThatHaveDefaultValues:
struct Foo {
var x: Int
var y: Int?
var z: Int! = 123
var w: Int? = 456
}
JSON: { "x": 1 }
Result with dontOverrideFieldsThatHaveDefaultValues strategy OFF:
{ x: 1, y: nil, z: nil, w: nil }
Result with dontOverrideFieldsThatHaveDefaultValues strategy ON:
{ x: 1, y: nil, z: Optional(123), w: Optional(456) }
Decoder: requreFieldsThatDontHaveDefaultValues:
struct Foo {
var x: Int?
var y: Int? = nil
var z: Int? = 123
}
JSON: {}
Result with requreFieldsThatDontHaveDefaultValues strategy OFF:
{ x: nil, y: nil, z: nil } // dontOverrideFieldsThatHaveDefaultValues = off
Result with requreFieldsThatDontHaveDefaultValues strategy OFF:
{ x: nil, y: nil, z: Optional(123) } // dontOverrideFieldsThatHaveDefaultValues = on
Result with requreFieldsThatDontHaveDefaultValues strategy ON:
// runtime error, x & y fields are missing
The above two might not be possible with JSONDecoder API as we currently have it. OTOH, if you are creating a new library you are more flexible, e.g. instead of having:
JSONDecoder().decode(T.self, from: data)
you may have:
MyJSONDecoder().decode(T(), from: data)
i.e. instead of passing a type you may pass an instance variable with is already filled out with default values, that are later:
- overridden by values from json if there is "field: value" in JSON (even if value in JSON is nil)
- not overridden if there is no corresponding "field: value" in JSON
Encoder: emitExplicitNil:
Example:
struct Foo {
var x: Int
var y: Int?
}
Value { x: 1, y: nil }
Result with emitExplicitNil strategy OFF: "{ "x": 1 }
Result with emitExplicitNil strategy ON: "{ "x": 1, "y": nil }
Edit:
Alternatively you may still have API of the form:
JSONDecoder().decode(T.self, from: data)
just have an additional requirement on T that it is "Inittable" (has init()) - that's how you can construct an instance inside and that instance will be filled with default values