Thank you for the proposal - it's a complex topic, so kudos for trying to solve it for us all.
Also a very big +1 for providing a solution to the problem.
Perhaps the proposal could mention that all keys (from enum case names and from associated value label names) will have the keyEncodingStrategy
and keyDecodingStrategy
of the JSONEncoder
and JSONDecoder
applied?
I would like to echo a few of the comments of @beccadax and throw in a small question:
In case of:
enum Command: Codable {
case load
}
If this were to encode as in one of the suggestions by @beccadax as:
{
"load": true
}
(here I agree that true
is the correct choice of value for the same reasons that Brent gives)
Then load
is clearly a key and the encoding of the key should follow the keyEncodingStrategy
of the (json) encoder.
If we chose to encode it without a keyed container as simply:
"load"
Then it is no longer a key and would not respect the keyEncodingStrategy.
It might be confusing for users to understand when a case might be a value and when it might be a key.
To me this confusion suggests the following rule:
If an enum is made Codable
, then all of it's cases should encode (and decode) to (and from) keyed containers using the case name as the key.
A question (where I feel I know the answer, but would like it clarified):
In case of the following:
enum Command: String, Codable {
case load
}
Here the compiler would use the existing Codable
conformance of RawRepresentable
(String
) instead of synthesizing this newly suggested conformance, right? Otherwise this would be a behavior breaking change.
I'd very much like to echo the suggestion from others that single unlabeled associated values should encode directly as values with the case as the key:
enum Command: Codable {
case load(String)
}
encodes as:
{
"load": "my associated value"
}
Like @George , I've written many, many manual Codable
enum conformances exactly in this way.
If this should not be the default, then I'd at least hope for some customization point that can give this behavior.
I think it would be ok to have codable synthesis for a number of well defined situations and refuse to synthesize conformance for other situations.
For instance perhaps don't try to synthesize the conformance when the associated values are a mix of labelled and unlabelled values?
Also perhaps don't try to synthesize the conformance when multiple cases share the same name?
I think the feature will provide a great value even with those two restrictions.
My personal wish list for the encoding of associated values:
- No values: encodes as
true
(using the reasoning that the case name must be a key and it thus must have a value - and the value should not be empty/null/falsey).
- Single unlabelled value: encodes the value directly
- Any number of labelled values (where all labels are unique): the values encode into a keyed container where the keys are the labels - and the keys can be customized as you suggest.
Thanks again - it will be awesome to have a solution for this in the language!
And also apologies from me for not having commented during the pitch fase.