我希望将模型对象存储在字典中,并希望使用 JSONEncoder
将整个字典序列化为数据,然后将其序列化为字符串并保存。
想法是使用 Swift 4 开箱即用的 Encodable
来确保我添加到字典中的任何内容都将被序列化,其中可以包括基元和自定义对象(它们本身将符合 可编码
)。
挑战是我应该将字典声明为什么类型:
- 如果我使用
[String: Any]
,它不知道如何编码Any
,如果我必须将它转换为实际的具体类型,它有点违背泛型的目的 - 如果我使用
[String: Encodable]
,它会在运行时崩溃并提示 Encodable 不符合自身,这是可以理解的,因为它 需要一个具体的类型
为了解决这个问题,我想到了创建一个包装器: 即具有关联类型的协议(protocol)或具有通用类型值的结构:
struct Serializable<T: Encodable> {
var value: T?
init(value: T) {
self.value = value
}
}
但问题依然存在,在声明上述字典的类型时,我仍然必须提供具体类型..
var dictionary: [String: Serializable<X>]
此处的“X”应该是什么,或者,实现此目标的正确方法是什么? 我错过了什么?
最佳答案
两种可能的方法:
您可以创建值为
Encodable
包装器类型的字典,它只是对基础值进行编码:struct EncodableValue: Encodable { let value: Encodable func encode(to encoder: Encoder) throws { try value.encode(to: encoder) } }
然后你可以这样做:
let dictionary = [ "foo": EncodableValue(value: Foo(string: "Hello, world!")), "bar": EncodableValue(value: Bar(value: 42)), "baz": EncodableValue(value: "qux") ] let data = try! JSONEncoder().encode(dictionary)
您可以定义自己的
Codable
类型而不是使用字典:struct RequestObject: Encodable { let foo: Foo let bar: Bar let baz: String } let requestObject = RequestObject( foo: Foo(string: "Hello, world!"), bar: Bar(value: 42), baz: "qux" ) let data = try! JSONEncoder().encode(requestObject)
不用说,这些都假定 Foo
和 Bar
都符合 Encodable
。
关于swift - 在 Swift 字典中存储 Encodable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48358371/