You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
String enums in dicts/lists are json serialized differently in Python 3.15 #148241
Cross posting from cattrs: python-attrs/cattrs#744
There's a difference in how Python 3.14 and Pytthon 3.15 handle json serialization of string enum values stored in other types which is exposed by cattrs tests.
I have failed to find any track record for this behavior in the available docs.
See:
Python 3.15.0a7
>>> import json
>>> from enum import Enum
>>> class AStringEnum(str, Enum):
... A = "a"
...
>>> val = AStringEnum.A
>>> json.dumps(val)
'"a"'
>>> in_dict = json.dumps({"key": val})
>>> in_dict
'{"key": "AStringEnum.A"}'
>>> parsed = json.loads(in_dict)
>>> type(parsed['key'])
<class 'str'>
>>> repr(parsed['key'])
"'AStringEnum.A'"
>>> AStringEnum(parsed['key'])
Traceback (most recent call last):
File "<python-input-15>", line 1, in <module>
AStringEnum(parsed['key'])
~~~~~~~~~~~^^^^^^^^^^^^^^^
File "/usr/lib64/python3.15/enum.py", line 732, in __call__returncls.__new__(cls, value)
~~~~~~~~~~~^^^^^^^^^^^^
File "/usr/lib64/python3.15/enum.py", line 1221, in __new__raise ve_exc
ValueError: 'AStringEnum.A' is not a valid AStringEnum
changed the title [-]String enums in dicts/lists are serialized differently in Python 3.15[/-][+]String enums in dicts/lists are json serialized differently in Python 3.15[/+]on Apr 8, 2026
Python 3.14: encoder_listencode_obj() => encoder_encode_string() => py_encode_basestring_ascii() => ascii_escape_unicode(). This function copies the string character by character using PyUnicode_READ().
Python 3.15: encoder_listencode_obj() => encoder_writer_string() => write_escaped_ascii(). This function calls PyUnicodeWriter_WriteStr() which calls PyObject_Str() since the dictionary key is a str subclass and not exactly the str type. PyObject_Str() returns AStringEnum.A string.
So the difference is in write_escaped_ascii() which now calls PyObject_Str() for str subclasses.
Activity
[-]String enums in dicts/lists are serialized differently in Python 3.15[/-][+]String enums in dicts/lists are json serialized differently in Python 3.15[/+]hugovk commentedon Apr 8, 2026
Reproducible with 3.15.0a1, and bisects to dec624e (PR #133239, issue #135336): "Add fast path to json string encoding".
cc @nineteendo @vstinner
StanFromIreland commentedon Apr 8, 2026
This is because the
__str__changed, on main:whereas previously:
vstinner commentedon Apr 8, 2026
Code to write the dictionary key:
encoder_listencode_obj()=>encoder_encode_string()=>py_encode_basestring_ascii()=>ascii_escape_unicode(). This function copies the string character by character usingPyUnicode_READ().encoder_listencode_obj()=>encoder_writer_string()=>write_escaped_ascii(). This function callsPyUnicodeWriter_WriteStr()which callsPyObject_Str()since the dictionary key is astrsubclass and not exactly thestrtype.PyObject_Str()returnsAStringEnum.Astring.So the difference is in
write_escaped_ascii()which now callsPyObject_Str()forstrsubclasses.vstinner commentedon Apr 8, 2026
Example:
Output on Python 3.15:
pythongh-148241: Fix json serialization for str subclasses
vstinner commentedon Apr 8, 2026
I created PR gh-148249 to fix the json regression.
I also created issue gh-148250 to discuss
PyUnicodeWriter_WriteStr()usage withstrsubclasses.gh-148241: Fix json serialization for str subclasses (#148249)
vstinner commentedon Apr 9, 2026
I close the issue, it has been fixed by the change b7e1d51. Thanks for the bug report!
pythongh-148241: Fix json serialization for str subclasses (python#14…
Address review feedback for the streaming JSON encoder