Swift-在解码可选的Codable值时,有没有办法区分不存在的字段还是nil / null的字段

时间:2019-02-13 11:46:04

标签: swift encoding decoding codable

必要的功能

我正在修改系统,以将当前未发送的API请求队列保存到UserDefaults,以便在用户连接允许时重新发送。

由于某些修补程序请求需要能够向API发送实际的NULL值(并且,如果其为nil可选,则不仅要忽略该字段),所以这意味着我需要能够对默认值的nil / NULL值进行编码和解码某些字段。

问题

我的编码方式朝下,可以愉快地编码请求以将NULL字段发送到服务器或将它们编码为Defaults。但是,我的问题是,在解码已保存的未发送请求时,我无法找到一种方法来区分实际的Nil值和不存在的字段。

我当前正在使用decodeIfPresent来解码我的字段(这些请求的所有字段都是可选的),如果该字段为空,或者如果该字段设置为Nil / NULL,则返回nil。显然,这对于我可以显式设置为Nil的字段不起作用,因为我无法区分这两种情况。

问题

我可以实现任何解码方法,以区分不存在的字段和实际设置为nil的字段吗?

1 个答案:

答案 0 :(得分:3)

没有办法,但是您可以添加其他信息以了解

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)

    }
}

根据文档decodeIfPresent

  

如果容器没有与键关联的值,或者该值为null,则此方法返回nil。这些状态之间的差异可以通过contains(_ :)调用来区分。

所以解码

let str = """
{
  "code" : 12
}
"""

给予

  

根(代码:可选(12),代码存在:可选(真))

&&

let str = """
{
  "code" : null
}
"""

给予

  

Root(代码:无,codeExists:可选(真))

还有这个

let str = """
{

}
"""

给予

  

根(代码:无,codeExists:可选(假))