将编码存储在Swift Dictionary中 [英] Store Encodables in a Swift Dictionary
问题描述
我正在寻找将模型对象存储在字典中,并希望使用 JSONEncoder
将整个字典序列化为数据,然后将其保存到字符串中并保存。
这个想法是使用Swift 4开箱即用的 Encodable
来确保我添加到字典中的任何东西都会被序列化其中可以包含基元和自定义对象(它们本身将符合 Encodable
)。
挑战是我应该声明字典的类型:
[String:Any]
,它不知道如何编码 Any
,如果必须如果我使用 [String:Encodable]
,它会将其转换为实际的具体类型,这有点违背泛型的用途。会在运行时崩溃,说
Encodable不符合自身,这是可以理解的,因为它
需要一个具体类型
$ b $为了解决这个问题,我想创建一个包装器:
ie一个关联类型为或的结构体,一个具有泛型类型值的结构体:
struct Serializable< T:Encodable> {
var value:T?
init(value:T){
self.value = value
}
}
但是问题仍然存在,在声明上述字典的类型时,我仍然需要提供具体的类型..
< pre $
var字典:[String:Serializable< X>]
'X'应该在什么位置,或者,实现这个目标的正确方法是什么?
我缺少什么?
两种可能的方法:
-
您可以创建字典,其值为
Encodable
封装类型,它简单地对基础值进行编码:struct EncodableValue:Encodable {
let value:可编码
func编码(到编码器:编码器)throws {
try value.encode(to:encoder)
}
}
然后你可以这样做:
let dictionary = [
foo:EncodableValue(value:Foo(string: )),
bar:EncodableValue(value:Bar(value:42)),
baz:EncodableValue(value:qux)
]
让data = try! JSONEncoder()。encode(dictionary)
-
你可以定义你自己的
Codable
类型,而不是使用字典:
struct RequestObject:Encodable {
let foo :Foo
让bar:Bar
让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
。
I'm looking to store models objects in a Dictionary and would like to serialize the whole dictionary using JSONEncoder
into data and subsequently into a string and save it.
The idea is to use Swift 4's out of the box Encodable
to ensure anything that I add to the dictionary will be serialized which can include primitives and custom objects (which will themselves conform to Encodable
).
The Challenge is what type should I declare the dictionary to be:
- If I use
[String: Any]
, it won't know how to encodeAny
, and if I have to cast it into an actual concrete type, it kind of defeats the purpose of generics - If I use
[String: Encodable]
, it will crash at run time saying Encodable doesn't conform to itself, which is understandable as it needs a concrete type
In order to tackle this, I thought of creating a wrapper: i.e A protocol with an associated type or a struct with generic type value:
struct Serializable<T: Encodable> {
var value: T?
init(value: T) {
self.value = value
}
}
But the problem remains, while declaring the type of the aforementioned dictionary, I still have to supply the concrete type..
var dictionary: [String: Serializable<X>]
What should 'X' be here, Or, what's the correct way to achieve this? What am I missing?
Two possible approaches:
You can create dictionary whose values are
Encodable
wrapper type that simply encodes the underlying value:struct EncodableValue: Encodable { let value: Encodable func encode(to encoder: Encoder) throws { try value.encode(to: encoder) } }
Then you can do:
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)
You can define your own
Codable
type instead of using dictionary: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)
Needless to say, these both assume that both Foo
and Bar
conform to Encodable
.
这篇关于将编码存储在Swift Dictionary中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!