Thanks for bringing this back up, Morten. I think my gut feeling has remained the same since last time:
From a principled standpoint (at least for me), adjusting the raw values of a type's CodingKeys
to match what a single encoder does isn't (or shouldn't be) the right approach. Unless one overrides the Codable
methods to use multiple pairs of keys, they're reused for all types — which means that a "quick" adjustment today to "fix" the results from JSON{En,De}coder
means that you propagate this weirdness to other formats/encoders.
To answer your questions, from my perspective:
- Yes, I think this issue warrants fixing
- I believe the issue can be fixed in Foundation alone. Details below
- I don't believe fixes would need to apply to the standard libraries; this is really between a type and
JSON{En,De}coder
I haven't had the opportunity to think this through entirely, but a thought: back in the mists of time, @Tony_Parker and I discussed the possibility of having JSON{En,De}coder
build in a list of known abbreviations which we could correctly identify as terms which would be correctly cased ("HTML", "URL", etc.) with the default .convert{To,From}SnakeCase
strategies, but didn't get to explore this idea at the time. I wasn't a fan of having Foundation hard-code a list of known values like this, and I still don't, but luckily it could be easy to extend to users:
enum JSONDecoder.KeyDecodingStrategy {
// ...
// Not entirely thought through: some options to maybe allow/ignore
// recognition at the beginning of a case name, like
// `htmlForURL` vs. `HTMLForURL`
case convertFromSnakeCaseWithKnownAbbreviations(Set<String>, options: SomeOptionType)
// ...
}
Sadly, I don't believe adding associated values to existing enum cases is ABI-stable, or else we could do something like
enum JSONDecoder.KeyDecodingStrategy {
case convertFromSnakeCase(knownAbbreviations: Set<String> = [], options: SomeOptionType = .default)
}
to maintain source stability, and not have to come up with a new case entirely.
Either way, this could give users an "in" to provide abbreviations their CodingKeys
use across an entire payload, and theoretically, they could revert changes to their CodingKeys
' raw values.
It would be up to them to scan through their CodingKeys
to find these abbreviations, or Foundation could provide at least a default list (JSONDecoder.KeyDecodingStrategy.defaultKnownAbbreviations
?) that could be extended with additional values before being passed in to the enum case. (I can see folks cargo-culting a "preferred" list of abbreviations either way, regardless of application, but I don't think that's worth worrying about.)
I haven't had time to fully think through this idea or its implications, so please poke holes if this obviously won't work for some reason, but I think this might be at least a compelling place to start exploring a fix in a contained way.
(Sadly, this does leave other encoders/decoders in the lurch if users have already adjusted CodingKeys
for this purpose and used them for other formats — but my gut feeling is that fixing the issue "at the source" might be a good start.)