Fix `JSONEncoder` key conversion for `CodingKeyRepresentable` dictionary keys
Summary
Fixes an issue where JSONEncoder incorrectly applied key encoding strategies (like .convertToSnakeCase) to dictionary keys that implement CodingKeyRepresentable, when these keys should preserve their semantic meaning and remain unchanged.
Problem
When encoding dictionaries with CodingKeyRepresentable keys (e.g., custom enum or struct keys), JSONEncoder was treating them as regular coding key values and applying key conversion strategies. This caused keys like "leaveMeAlone" to be transformed to "leave_me_alone" even when the key itself represents a semantic identifier that should remain unchanged.
Solution
- Expands the existing
_JSONStringDictionaryEncodableMarkerprotocol to cover anyCodingKeyRepresentable-keyed dictionaries, not justString-keyed ones. - Renames the protocol to
_JSONCodingKeyRepresentableDictionaryEncodableMarkerto reflect its broader scope. - Updates the encoding logic to convert
CodingKeyRepresentablekeys directly to their string representation without applying encoding transformations.
Test Plan
Added test case encodingDictionaryCodingKeyRepresentableKeyConversionUntouched() that verifies:
- Dictionary with
CodingKeyRepresentablekeys preserves original key names. - Key encoding strategies like
.convertToSnakeCaseare not applied to the dictionary keys. - The fix works with custom structs implementing
CodingKeyRepresentable.
Checklist
- [x] Added test coverage for the fix
- [x] All existing tests pass
- [x] Code follows Swift Foundation conventions
- [x] Changes are backward compatible
This change ensures that dictionaries with semantic keys maintain their intended structure while still allowing key encoding strategies to work correctly for object properties during regular encoding.
@swift-ci please test
Hi @itingliu, I rebased the PR and seems the CI work needs to be run again, can you help?
Would anyone be able to lend a hand with running the test and reviewing this?