简体   繁体   中英

Type does not conform to protocol 'Encodable'

I have a class named Event that I want to make it Codable:

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)
        }
    }
}

but I'm getting this error:

Type 'Event' does not conform to protocol 'Encodable'

I implemented both init(from decoder: Decoder) and encode(from encoder: Encoder) . so what I'm doing wrong here?

I need data property with [String:Any] type, because my users need to store some json-like information with it.

This is how you can use ANY in Codable

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM