大佬教程收集整理的这篇文章主要介绍了json – 如何解码类型依赖于标记的值数组?,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
[ { "tag": "Foo",… },{ "tag": "Bar",{ "tag": "Baz",]
我想将此数组解码为一个结构数组,其中特定类型取决于标记:
protocol someCommonType {} struct Foo: Decodable,someCommonType { … } struct Bar: Decodable,someCommonType { … } struct Baz: Decodable,someCommonType { … } let values = try JSONDecoder().decode([someCommonType].self,from: …)
我怎么做?目前我有这个有点丑陋的包装:
struct DecodingWrapper: Decodable { let value: someCommonType public init(from decoder: Decoder) throws { let c = try decoder.singleValueContainer() if let decoded = try? c.decode(Foo.self) { value = decoded } else if let decoded = try? c.decode(Bar.self) { value = decoded } else if let decoded = try? c.decode(Baz.self) { value = decoded } else { throw … } } }
然后:
let wrapped = try JSONDecoder().decode([DecodingWrapper].self,from: …) let values = wrapped.map { $0.value }
有没有更好的办法?
以这种方式看待它:你有一系列都有标签的东西,有些属于这种类型,有些属于完全不同的类型,还有其他……有时你甚至都不认识标签. Swift enum是捕捉这一想法的完美载体.
所以你有一堆结构共享一个标签属性,但彼此完全不同:
struct Foo: Decodable { let tag: String let fooValue: Int } struct Bar: Decodable { let tag: String let barValue: Int } struct Baz: Decodable { let tag: String let bazValue: Int }
并且您的数组可以包含上述类型的任何实例,或者包含未知类型的实例.所以你有enum TagggedThing(或更好的名字).
enum TagggedThing { case foo(Foo) case bar(Bar) case baz(Baz) case unknown }
你的数组,用Swift术语,是[TagggedThing]类型.所以你将TagggedThing类型与Decodable一致,如下所示:
extension TagggedThing: Decodable { private enum CodingKeys: String,CodingKey { case tag } init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) let tag = try container.decode(String.self,forKey: .tag) let singleValueContainer = try decoder.singleValueContainer() switch tag { case "foo": // if it's not a Foo,throw and blame the server guy self = .foo(try singleValueContainer.decode(Foo.self)) case "bar": self = .bar(try singleValueContainer.decode(Bar.self)) case "baz": self = .baz(try singleValueContainer.decode(Baz.self)) default: // this tag is unknown,or known but we don't care self = .unknown } } }
现在您可以解码以下JSON:
let json: Data! = """ [ {"tag": "foo","fooValue": 1},{"tag": "bar","barValue": 2},{"tag": "baz","bazValue": 3} ] """.data(using: .utf8)
像这样:
let taggedThings = try? JSONDecoder().decode([TagggedThing].self,from: json)
以上是大佬教程为你收集整理的json – 如何解码类型依赖于标记的值数组?全部内容,希望文章能够帮你解决json – 如何解码类型依赖于标记的值数组?所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。