我有一个名为 Event 的类,我想让它成为可编码的:
class Event: Codable {
let name: String
let action: String
let data: [String: Any]?
enum CodingKeys: String, CodingKey {
case name
case action
case data
}
init(name: String, action: String, data: [String: Any]?) {
self.name = name
self.action = action
self.data = data
}
required init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
self.name = try values.decode(String.self, forKey: .name)
self.action = try values.decode(String.self, forKey: .action)
let eventDataAsJSONString = try values.decode(String.self, forKey: .data)
if let eventDataAsData = eventDataAsJSONString.data(using: .utf8) {
self.data = try? JSONSerialization.jsonObject(with: eventDataAsData, options: []) as? [String: Any]
} else {
self.data = nil
}
}
func encode(from encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(self.name, forKey: .name)
try container.encode(self.action, forKey: .action)
if let data = self.data {
let eventDataAsData = try! JSONSerialization.data(withJSONObject: data, options: [])
let eventDataAsJSONString = String(data: eventDataAsData, encoding: .utf8)
try container.encode(eventDataAsJSONString, forKey: .data)
} else {
try container.encodeNil(forKey: .data)
}
}
}
Run Code Online (Sandbox Code Playgroud)
但我收到此错误:
Type 'Event' does not conform to protocol 'Encodable'
Run Code Online (Sandbox Code Playgroud)
我实现了init(from decoder: Decoder)和encode(from encoder: Encoder)。所以我在这里做错了什么?
data带[String:Any]类型的属性,因为我的用户需要用它存储一些类似 json 的信息。这就是你如何在 Codable 中使用 ANY
class Event<T: Codable>: Codable {
let name: String
let action: String
let data: [String: T]?
enum CodingKeys: String, CodingKey {
case name
case action
case data
}
init(name: String, action: String, data: [String: T]?) {
self.name = name
self.action = action
self.data = data
}
required init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
self.name = try values.decode(String.self, forKey: .name)
self.action = try values.decode(String.self, forKey: .action)
let eventDataAsJSONString = try values.decode(String.self, forKey: .data)
if let eventDataAsData = eventDataAsJSONString.data(using: .utf8) {
self.data = try? JSONSerialization.jsonObject(with: eventDataAsData, options: []) as? [String: T]
} else {
self.data = nil
}
}
func encode(from encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(self.name, forKey: .name)
try container.encode(self.action, forKey: .action)
if let data = self.data {
let eventDataAsData = try! JSONSerialization.data(withJSONObject: data, options: [])
let eventDataAsJSONString = String(data: eventDataAsData, encoding: .utf8)
try container.encode(eventDataAsJSONString, forKey: .data)
} else {
try container.encodeNil(forKey: .data)
}
}
}
let event = Event<String>(name: "name", action: "action", data: ["String" : "String"]) // Replace <String> with the type u want and pass that in data
Run Code Online (Sandbox Code Playgroud)