dataclasses-json
dataclasses-json copied to clipboard
Dataclass fields are not serialized in definition order when explicitly building schema
This library does not seem to support dataclass member ordering when serializing objects using a pregenerated schema created with the schema
method unless I missed something. However since marshmallow Meta objects explicitly support keeping dataclass fields in the definition order with the ordered
parameter this is probably just an oversight?
Currently dataclass fields are in a random order in the serialized output every time the script is run. (The to_json
method does work as expected.) Below is sample code that demonstrates the issue.
from dataclasses import dataclass
from dataclasses_json import dataclass_json
@dataclass_json
@dataclass
class Person:
first_name: str
last_name: str
age: int
person = Person(first_name="Jane", last_name="Doe", age=30)
person_schema = Person.schema()
print("Person:", person_schema.dumps(person))
print("Expected:", '{"first_name": "Jane", "last_name": "Doe", "age": 30}')
The code will have a chance of returning the following output:
Person: {"last_name": "Doe", "age": 30, "first_name": "Jane"} Expected: {"first_name": "Jane", "last_name": "Doe", "age": 30}
After debugging for a while I figured out that to fix this I simply needed to add the following line:
'ordered': True,
To mm.py in the build_schema
function on line 328. After applying the fix the serialized output always matches the expected output.
I think the library should provide an option to keep dataclass fields in definition order (preferably on by default) in the serialized output. Or just always keep them in order like the to_json
method does.
Hi, thanks for reporting this issue. Agreed, that the behavior should be configurable.
As for why this is happening, here's a blurb from the json
documentation (which backs to_json
):
Prior to Python 3.7, dict was not guaranteed to be ordered, so inputs and outputs were typically scrambled unless collections.OrderedDict was specifically requested.
So I guess this issue might also happen for to_json
in 3.6
I would also like to see this feature made available.
+1 What I've did for now is set:
schema.dump_fields = schema.declared_fields
This works for me because all declared fields must be dumped.