I'm not sure it needs to be that complicated.
Currently, if the JSONEncoder detects a
[String: Encodable] dictionary, it manually iterates the key-value pairs, encodes the value, and places the result in an NSMutableDictionary.
It should be possible to instead:
- iterate the key-value pairs
- encode the key in to a separate container
- validate that the container holds exactly one String (however deeply nested it may be)
- associate that String with the value in the resulting NSMutableDictionary.
This would naturally allow all other primitive types (like Date), as well as single-item arrays of primitives, to be encoded when they are used as dictionary keys. The important thing is that your key-type boils down in to a single String when encoded. That seems like a more reasonable limitation, based on how your values encode relative to the JSON spec, rather than how you model them in the Swift type system (which really has nothing at all to do with JSON).
JSONDecoder similarly detects dictionaries, so we can create a custom Decoder which does the reverse: it only has a single String, so any object-graph you inflate from it can only decode a single value, however deeply-nested it may be. That's simple enough to validate.
I have a rough patch which does that, and it appears to work without regressing anything in the test suite. I'll need to check a bunch of edge-cases before it's ready for a PR though (not that I expect it to ever be merged).