如何解码许多可解码 Swift 中的单个异常属性?

问题描述

我有一个符合可解码的结构。它有 50 个字符串属性和只有一个布尔值。该 bool 来自服务器,如字符串“false”/“true”或有时像整数 0/1,因此无法从框中解码。我怎样才能让它解码但不写大量的所有 50 个字符串属性的手动解码?也许以某种方式覆盖 Bool 的 decodeIfPresent,但我无法让它工作。 我如何才能避免通过手动解码所有内容和所有内容并仅处理那个 Bool 来创建 init?如果可能,不使用计算属性。

struct Response: Decodable {
    var s1: String
    var s2: String
    var s3: String
    //...........
    var s50: String
    var b1: Bool
    var b2: Bool
}

这里是 json 示例:

{
    "s1":"string"
    "s2":"string"
    "s3":"string"
    //..........
    "s50":"string"
    "b1":"true"
    "b2":"0"
}

试过这个但不起作用(((

extension KeyedDecodingContainer { //Doesn't work,no execution
    func decodeIfPresent(_ type: Bool.Type,forKey key: K) throws -> Bool {
        return try! self.decodeIfPresent(Bool.self,forKey: key)
    }
    func decodeIfPresent(_ type: Bool.Type,forKey key: K) throws -> Bool? {
        return try? self.decodeIfPresent(Bool.self,forKey: key)
    }
}

解决方法

解决这个问题的一种方法是编写一个处理自定义解码的属性包装器,如下所示:

TreeEnsembleSerialize

像这样使用它:

@propertyWrapper
struct FunnyBool: Decodable {
    var wrappedValue: Bool

    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        if let value = try? container.decode(Bool.self) {
            wrappedValue = value
        }
        else if
            let string = try? container.decode(String.self),let value = Bool(string)
        {
            wrappedValue = value
        }
        else if
            let int = try? container.decode(Int.self),let value = int == 0 ? false : int == 1 ? true : nil
        {
            wrappedValue = value
        }
        else {
            // Default...
            wrappedValue = false
        }
    }
}

游乐场输出:

struct Response: Decodable {
    var s1: String
    var s2: String
    @FunnyBool var b: Bool
}

let json = #"{ "s1": "hello","s2": "world","b": 1 }"#
let response = try! JSONDecoder().decode(Response.self,from: json.data(using: .utf8)!)
dump(response)

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...