我有以下 Swift 代码
func doStuff<T: Encodable>(payload: [String: T]) {
let jsonData = try! JSONEncoder().encode(payload)
// Write to file
}
var things: [String: Encodable] = [
"Hello": "World!",
"answer": 42,
]
doStuff(payload: things)
导致错误
Value of protocol type 'Encodable' cannot conform to 'Encodable'; only struct/enum/class types can conform to protocols
如何解决?我想我需要更改things
的类型,但我不知道该怎么做。
附加信息:
如果我将doStuff
更改为非通用,我只会在该函数中遇到相同的问题
func doStuff(payload: [String: Encodable]) {
let jsonData = try! JSONEncoder().encode(payload) // Problem is now here
// Write to file
}
Encodable
不能用作带批注的类型。它只能用作泛型约束。JSONEncoder
只能对具体类型进行编码。
函数
func doStuff<T: Encodable>(payload: [String: T]) {
是正确的,但不能使用[String: Encodable]
调用函数,因为协议无法符合自身。这正是错误消息所说的。
主要问题是things
的真实类型是[String:Any]
的,Any
无法编码。
必须使用JSONSerialization
序列化things
或创建帮助程序结构。
您可以将where
关键字与Value
类型结合使用,如下所示:
func doStuff<Value>(payload: Value) where Value : Encodable {
...
}
您正在尝试使T
符合Encodable
如果T == Encodable
,这是不可能的。协议不符合自身。
相反,您可以尝试:
func doStuff<T: Hashable>(with items: [T: Encodable]) {
...
}
您尝试执行的操作可以通过协议扩展实现:
protocol JsonEncoding where Self: Encodable { }
extension JsonEncoding {
func encode(using encoder: JSONEncoder) throws -> Data {
try encoder.encode(self)
}
}
extension Dictionary where Value == JsonEncoding {
func encode(using encoder: JSONEncoder) throws -> [Key: String] {
try compactMapValues {
try String(data: $0.encode(using: encoder), encoding: .utf8)
}
}
}
您Dictionary
中的每种类型都需要符合我们的JsonEncoding
协议。您使用了String
和Int
,因此以下是为这两种类型添加一致性的扩展:
extension String: JsonEncoding { }
extension Int: JsonEncoding { }
这是你的代码做你想让它做的事情:
func doStuff(payload: [String: JsonEncoding]) {
let encoder = JSONEncoder()
do {
let encodedValues = try payload.encode(using: encoder)
let jsonData = try encoder.encode(encodedValues)
// Write to file
} catch {
print(error)
}
}
var things: [String: JsonEncoding] = [
"Hello": "World!",
"answer": 42
]
doStuff(payload: things)
你没有问解码,所以我没有在这里解决。您要么必须知道哪种类型与什么键相关联,要么必须创建一个尝试解码值的顺序(应该将1
转换为Int
还是Double
......
我回答了你的问题,没有质疑你的动机,但对于你想要做的事情,可能有一个更好、更"快速"的解决方案......