If I have a struct that conforms to the Codable
protocol like so:
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?
}
How can I create an encoder & a decoder that encodes / decodes it to / from an instance of type Dictionary<String, Any?>
like so?
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: I'm aware that it's possible to use the JSONEncoder
and JSONDecoder
classes before casting the result to a dictionary object, but I don't want that for efficiency reasons.
The Swift standard library comes with the JSONEncoder
and JSONDecoder
as well as the PListEncoder
and PListDecoder
classes right out the box which conform to the Encoder
and Decoder
protocols respectively.
My problem is that I have no clue how to implement these protocols for my custom encoder and decoder classes:
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 {
}
}
Given that Swift is open sourced, it's possible to view the source code of the JSONEncoder and PListEncoder classes in the standard library, but the source files are huge and difficult to understand due to the lack of documentation apart from a few comments.
If you look at the implementation of JSONDecoder
(here), you'll see that it's a two-step process: 1. use JSONSerialization
to convert the Data
into an json dictionary, then 2. create an instance of an internal class _JSONDecoder
to do the dictionary -> Codable
object conversion.
There is some discussion on the Swift forums on possibly exposing the internal types, and the Swift team may do something about it in the future. Someone also offered up a 3rd party framework for doing what you want.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With