协议类型"可编码"的值不能符合"可编码";只有结构/枚举/类类型可以符合协议



我有以下 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协议。您使用了StringInt,因此以下是为这两种类型添加一致性的扩展:

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......

我回答了你的问题,没有质疑你的动机,但对于你想要做的事情,可能有一个更好、更"快速"的解决方案......

最新更新