![](/img/trans.png)
[英]Value of protocol type 'Any' cannot conform to 'Equatable'; only struct/enum/class types can conform to protocols
[英]Value of protocol type 'Encodable' cannot conform to 'Encodable'; only struct/enum/class types can conform to protocols
我有以下 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
更改為不是通用的,我只會在 function 中遇到同樣的問題
func doStuff(payload: [String: Encodable]) {
let jsonData = try! JSONEncoder().encode(payload) // Problem is now here
// Write to file
}
Encodable
不能用作帶注釋的類型。 它只能用作通用約束。 而JSONEncoder
只能編碼具體類型。
function
func doStuff<T: Encodable>(payload: [String: T]) {
是正確的,但是您不能使用[String: Encodable]
調用 function,因為協議不能符合自身。 這正是錯誤消息所說的。
主要問題是things
的真實類型是[String:Any]
並且Any
無法編碼。
您必須使用JSONSerialization
序列化things
或創建輔助結構。
您正在嘗試使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
...)。
我在沒有質疑您的動機的情況下回答了您的問題,但是對於您正在嘗試做的事情,可能有一個更好、更“迅速”的解決方案......
您可以將where
關鍵字與Value
類型結合使用,如下所示:
func doStuff<Value>(payload: Value) where Value : Encodable {
...
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.