仅在运行时知道类型时的SWIFT 4 JSON解码 [英] Swift 4 JSON decoding when type is only known at runtime

查看:47
本文介绍了仅在运行时知道类型时的SWIFT 4 JSON解码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当要解码的类型在运行时仅已知时,是否可以使用SWIFT 4中的Decodable协议对JSON对象进行解码?

我有一个各种各样的注册表,它将String标识符映射到我们要解码的类型,如下所示:

import Foundation

struct Person: Decodable {
    let forename: String
    let surname: String
}

struct Company: Decodable {
    let officeCount: Int
    let people: [Person]
}

let registry: [String:Decodable.Type] = [
    "Person": Person.self,
    "Company": Company.self
]

let exampleJSON = """
{
    "forename": "Bob",
    "surname": "Jones"
}
""".data(using: .utf8)!

let t = registry["Person"]!

try! JSONDecoder().decode(t, from: exampleJSON) // doesn't work :-(

我说对了吗?还是有更好的办法?

推荐答案

您的设计确实很独特,但不幸的是,我认为您遇到了SWIFT类型系统的边缘问题。基本上,协议不符合其自身,因此,您的一般Decodable.Type在这里是不够的(即,您确实需要一个具体的类型来满足类型系统要求)。这可能解释了您出现的错误:

无法使用类型为(Decodable.Type, from: Data)的参数列表调用decode。需要(T.Type, from: Data)类型的参数列表。

但是,话虽如此,确实有一个(脏的!)绕过这件事。首先,创建一个虚拟DecodableWrapper来保存您的运行时类型Decodable

struct DecodableWrapper: Decodable {
    static var baseType: Decodable.Type!
    var base: Decodable

    init(from decoder: Decoder) throws {
        self.base = try DecodableWrapper.baseType.init(from: decoder)
    }
}

然后这样使用:

DecodableWrapper.baseType = registry["Person"]!
let person = try! JSONDecoder().decode(DecodableWrapper.self, from: exampleJSON).base
print("person: (person)")

打印预期结果:

人:人(名:"Bob",姓:"Jones")

这篇关于仅在运行时知道类型时的SWIFT 4 JSON解码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆