If there are indeed exceptions, the question is — who would best know about them and where they should be? Is it the Encoder
itself? The individual objects? The entity doing the actual encoding (e.g. the code that calls XMLEncoder().encode(...)
)?
There are solutions to this and in the design of our APIs, we've tried to keep all options open, so any of these three actors can influence the final decision in concert with one another:
- Individual objects generally shouldn't need to know about the wire formats/what's going on elsewhere in encoding/decoding, but they can through the encoder's
codingPath
(AKA "where are we in the process right now?") and theuserInfo
dictionary (AKA "what details might I need to know from the top level down?"). So if you need to, individual objects can decide to inform theEncoder
about what to do - The entity doing the encoding generally shouldn't muck around with individual objects and types they don't know about, but they can if the
Encoder
provides strategies which allow overriding of individual types (likeDateEncodingStrategy
). A.custom
strategy can offer callbacks to the top-level to influence how things are encoded - An
Encoder
generally shouldn't special-case various things during encoding, but can do whatever it wants or needs to do to get the payload encoded
All in all, you can attack this problem from any of the three directions. The question is: who has the information (or can provide it) to best inform how things are encoded?
Why? You don't necessarily have to — you can have a single Encoder
which changes serialization schemes as it's going through and encoding. I don't think there's necessarily anything keeping the Encoder
from doing a combination of several different methods, as long as it knows what's needed.
There's some amount of balance to strike here between idealism and pragmatism. Your type could be encoded in a variety of different formats, but will it? If so, and your type cares so strongly about the details of all possible formats that you can't reflect this in the model structure, there are other ways of dealing with it.
One way is to switch on the output format (there are some ways of doing this, but it largely requires participation from the Encoder
or the top-level entity at the moment) and to wrap at encode(to:)
-time the properties you want to encode in the specific wire formats you want.
Another option is to incorporate Codable
adaptors somehow (we haven't yet designed this, but it's come up a few times), letting you more easily modify the behavior of individual properties; no promises on this ATM.
Yeah, as mentioned above, this is one way to do it. There are many, but it depends on specific needs rather than hypotheticals.
As noted by @krilnon, Int
-backed CodingKeys
get both String
and Int
values (String
value matching the name of the case, Int
value based on its value).