如何解决具有自定义结构的Swift JSONEncoder编码通用类型
我目前正在尝试使用T
对具有这种类型属性的通用结构(JSONEncoder
)进行编码:
struct A <T:Codable> : Codable {
var id: Int
var attribute : T
init(id: Int,attribute: T){
self.id = id
self.attribute = attribute
}
}
struct B : Codable {
var name: String
var age: Int
}
let encoder = JSONEncoder()
let foo = A<B>(id: 1,attribute: B(name: "name",age: 29))
try? encoder.encode(foo)
这将导致如下所示的JSON:
{
"id" : 1,"attribute" : {
"name" : "name","age" : 29
}
}
但是我想自定义编码以使嵌套属性达到根级别:
{
"id" : 1,"name" : "name","age" : 29
}
使用自定义CodingKey
结构对我不起作用,因为T
可能具有任意数量的属性,并且键(属性名称)事先未知。
解决方法
这需要通过实现encode(to:)
和init(from:)
来手动完成:
struct A <T:Codable> {
var id: Int
var attribute : T
}
extension A: Codable {
enum CodingKeys: CodingKey { case id }
func encode(to encoder: Encoder) throws {
// use attribute's own encode(to:)
try attribute.encode(to: encoder)
// then encode the id
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(id,forKey: .id)
}
init(from decoder: Decoder) throws {
// use attribute's own init(from:)
self.attribute = try T.init(from: decoder)
// decode the id
let container = try decoder.container(keyedBy: CodingKeys.self)
self.id = try container.decode(Int.self,forKey: .id)
}
}
请注意,这是一个非常脆弱的解决方案。我不建议按照您的计划进行编码。。
如果EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP,subcode=0x0)
的编码容器与T
的编码容器(是键容器)
例如,以下内容在运行时失败:
A
这是因为当let a = A(id: 1,attribute: "A")
let data = JSONEncoder().encode(a)
是T
时,其容器是String
。如果SingleValueEncodingContainer
是一个数组,也会发生同样的情况:
T
因为数组是用let a = A(id: 1,attribute: ["A"])
编码的
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。