7

如果我有一个符合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)

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

Swift 标准库带有开箱即用的JSONEncoderJSONDecoder以及PListEncoder和类,它们分别符合和协议。PListDecoderEncoderDecoder

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

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 是开源的,因此可以在标准库中查看JSONEncoderPListEncoder类的源代码,但是由于缺少文档,除了一些注释之外,源文件非常庞大且难以理解。

4

1 回答 1

1

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

Swift 论坛上有一些关于可能暴露内部类型的讨论,Swift 团队将来可能会对此做一些事情。有人还提供了一个 3rd 方框架来做你想做的事。

于 2018-01-24T16:10:35.197 回答