【问题标题】:Custom Dictionary Encoder & Decoder for the Codable protocol in Swift 4Swift 4 中 Codable 协议的自定义字典编码器和解码器
【发布时间】:2018-03-31 12:54:05
【问题描述】:

如果我有一个符合Codable 协议的结构,如下所示:

enum AnimalType: String, Codable {
    case dog
    case cat
    case bird
    case hamster
}

struct Pet: Codable {
    var name: String
    var animalType: AnimalType
    var age: Int
    var ownerName: String
    var pastOwnerName: String?
}

我怎样才能创建一个编码器和一个解码器,像这样将它编码/解码到/从Dictionary<String, Any?> 类型的实例?

let petDictionary: [String : Any?] = [
    "name": "Fido",
    "animalType": "dog",
    "age": 5,
    "ownerName": "Bob",
    "pastOwnerName": nil
]
let decoder = DictionaryDecoder()
let pet = try! decoder.decode(Pet.self, for: petDictionary)

NB:我知道在将结果转换为字典对象之前可以使用 JSONEncoder 和 JSONDecoder 类,但出于效率原因,我不希望这样做。

Swift 标准库带有 JSONEncoder 和 JSONDecoder 以及 PListEncoder 和 PListDecoder 类,它们分别符合 Encoder 和 Decoder 协议。

我的问题是我不知道如何为我的自定义编码器和解码器类实现这些协议:

class DictionaryEncoder: Encoder {

    var codingPath: [CodingKey]

    var userInfo: [CodingUserInfoKey : Any]

    func container<Key>(keyedBy type: Key.Type) -> KeyedEncodingContainer<Key> where Key : CodingKey {

    }

    func unkeyedContainer() -> UnkeyedEncodingContainer {

    }

    func singleValueContainer() -> SingleValueEncodingContainer {

    }
}
class DictionaryDecoder: Decoder {

    var codingPath: [CodingKey]

    var userInfo: [CodingUserInfoKey : Any]

    func container<Key>(keyedBy type: Key.Type) throws -> KeyedDecodingContainer<Key> where Key : CodingKey {

    }

    func unkeyedContainer() throws -> UnkeyedDecodingContainer {

    }

    func singleValueContainer() throws -> SingleValueDecodingContainer {

    }
}

鉴于 Swift 是开源的,可以在标准库中查看 JSONEncoder 和 PListEncoder 类的源代码,但由于缺少文档,源文件巨大且难以理解几厘米。

【问题讨论】:

  • 如果你不想使用 JSONDecoder 那为什么要实现 Codable 协议呢?
  • Codable 协议是泛化/通用的,可用于表示具有原生 Swift 类型的外部数据结构。 Swift 标准库具有 Encoder 和 Decoder 协议,您可以实现这些协议来为 Codable 协议创建自己的自定义编码器和解码器。 Swift 标准库带有两个这样的编码器/解码器对:github.com/apple/swift/blob/master/stdlib/public/SDK/Foundation/…github.com/apple/swift/blob/master/stdlib/public/SDK/Foundation/…
  • 我的问题是那里的代码太复杂了,除了代码库中的 cmets 之外,没有文档说明如何实现自己的符合 Encoder 的自定义编码器和解码器和Decoder 协议。

标签: swift dictionary encoder decoder codable


【解决方案1】:

如果你看一下JSONDecoder(here)的实现,你会发现这是一个两步的过程:1.使用JSONSerialization将Data转换成json字典,然后2 .创建一个内部类_JSONDecoder的实例来做字典->Codable对象转换。

some discussion on the Swift forums 可能会暴露内部类型,Swift 团队将来可能会对此采取一些措施。有人还提供了一个 3rd 方框架来做你想做的事。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-01-25
    • 2018-05-23
    • 2017-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-11
    • 1970-01-01
    相关资源
    最近更新 更多