Reputation: 43
I'm in the process of modifying a system to save a queue of currently unsent API requests to UserDefaults to be re-sent when the user's connection allows.
As some patch requests require the ability to send an actual NULL value to the API (and not just ignore out the field if its a nil optional), this means I need the ability to encode and decode nil/NULL values from defaults for certain fields.
I have the encoding side down, and can happily encode requests to either send NULL fields to the server or encode them to Defaults. However, my issue is that when it comes to decoding saved unsent requests, I can't find a way to differentiate between an actual Nil value and the field just not being there.
I am currently using decodeIfPresent to decode my fields (all of the fields for these requests are optional), which returns nil if the field is empty OR if the field is set to Nil/NULL. Obviously this doesn't work for my fields that can explicitly be set to Nil, as there is no way for me to differentiate between the two cases.
Is there any decode methodology I could implement that would allow for differentiating between a field not being there and a field actually being set to nil?
Upvotes: 4
Views: 400
Reputation: 100503
There is no way , but you can add another info to know that
struct Root : Codable {
let code : Int?
let codeExists:Bool?
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
code = try values.decodeIfPresent(Int.self, forKey: .code)
codeExists = values.contains(.code)
}
}
According to docs decodeIfPresent
This method returns nil if the container does not have a value associated with key, or if the value is null. The difference between these states can be distinguished with a contains(_:) call.
So decoding
let str = """
{
"code" : 12
}
"""
gives
Root(code: Optional(12), codeExists: Optional(true))
&&
This
let str = """
{
"code" : null
}
"""
gives
Root(code: nil, codeExists: Optional(true))
and this
let str = """
{
}
"""
gives
Root(code: nil, codeExists: Optional(false))
Upvotes: 4