Repository navigation
Commit a1ebbcd
authored
Fix json.encode of a dict keyed by a plain str Enum (#1118)
### Problem
Encoding a dict whose keys are members of a plain `enum.Enum` with `str`
values
raises, even though the same key type round-trips through every other
path:
```python
import msgspec, enum
class Fruit(enum.Enum):
APPLE = "apple"
BANANA = "banana"
msgspec.json.decode(b'{"apple": 1}', type=dict[Fruit, int]) # ok
msgspec.msgpack.encode({Fruit.APPLE: 1}) # ok
msgspec.to_builtins({Fruit.APPLE: 1}) # ok -> {'apple': 1}
msgspec.json.encode({Fruit.APPLE: 1})
# TypeError: Only dicts with str-like or number-like keys are supported
```
`dict[Fruit, int]` is an accepted *decode* type and both
`msgpack.encode` and
`to_builtins` handle the key, so `json.encode` rejecting it is a
cross-codec
inconsistency.
### Cause
`json_encode_enum` routes a key's underlying value through
`json_encode_dict_key_noinline`, which only handles non-`str` keys
(`str` keys
are fast-pathed in `json_encode_dict_key`). A plain `str`-valued enum
therefore
hits the "unsupported key" error.
### Fix
When encoding an enum as a dict key, write a `str` value straight to the
key
with `json_encode_str`; non-`str` values keep going through
`json_encode_dict_key_noinline` as before.
### Tests
`test_encode_dict_plain_enum_str_key` covers a plain str `Enum` used as
a dict
key (encode output and encode/decode round-trip), and `FruitStr` is
added to the
existing mixed-key-type dict test.
`pytest tests/unit/test_json.py` → 1786 passed.1 parent 9fdf482 commit a1ebbcd
2 files changed
Lines changed: 54 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
14153 | 14153 | | |
14154 | 14154 | | |
14155 | 14155 | | |
14156 | | - | |
14157 | | - | |
14158 | | - | |
| 14156 | + | |
| 14157 | + | |
| 14158 | + | |
| 14159 | + | |
| 14160 | + | |
| 14161 | + | |
| 14162 | + | |
| 14163 | + | |
| 14164 | + | |
| 14165 | + | |
| 14166 | + | |
| 14167 | + | |
| 14168 | + | |
| 14169 | + | |
14159 | 14170 | | |
14160 | 14171 | | |
14161 | 14172 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2019 | 2019 | | |
2020 | 2020 | | |
2021 | 2021 | | |
| 2022 | + | |
2022 | 2023 | | |
2023 | 2024 | | |
2024 | 2025 | | |
| |||
2037 | 2038 | | |
2038 | 2039 | | |
2039 | 2040 | | |
| 2041 | + | |
| 2042 | + | |
| 2043 | + | |
| 2044 | + | |
| 2045 | + | |
| 2046 | + | |
| 2047 | + | |
| 2048 | + | |
| 2049 | + | |
| 2050 | + | |
| 2051 | + | |
| 2052 | + | |
| 2053 | + | |
| 2054 | + | |
| 2055 | + | |
| 2056 | + | |
| 2057 | + | |
| 2058 | + | |
| 2059 | + | |
| 2060 | + | |
| 2061 | + | |
| 2062 | + | |
| 2063 | + | |
| 2064 | + | |
| 2065 | + | |
| 2066 | + | |
| 2067 | + | |
| 2068 | + | |
| 2069 | + | |
| 2070 | + | |
| 2071 | + | |
| 2072 | + | |
| 2073 | + | |
| 2074 | + | |
| 2075 | + | |
| 2076 | + | |
| 2077 | + | |
| 2078 | + | |
| 2079 | + | |
2040 | 2080 | | |
2041 | 2081 | | |
2042 | 2082 | | |
| |||
0 commit comments