0

Taking from attrs example here but adding group_id & name. I want to create data classes so I can then export them to JSON using json.dump().

@define
class User:
    email: str
    password: str
    name: str = field(default="No name")

@define
class UserList:
    users: list[User]
    group_id: str = field(default=str(uuid4()), on_setattr=frozen)

json.dump(asdict(UserList([User("jane@doe.invalid", "s33kred"),
                 User("joe@doe.invalid", "p4ssw0rd")]),
       filter=lambda attr, value: attr.name != "password"))

That prints out this:

{"users": [{"email": "jane@doe.invalid"}, {"email": "joe@doe.invalid"}, {"name": "No name"}], "group-id": "a9fc0c10-125f-4c65-a901-ac16e3b57bc7"}

However, my issue is that I want group-id to be at the very top and name to be the first one in the list. Something like this:

{"group-id": "a9fc0c10-125f-4c65-a901-ac16e3b57bc7", "users": [{"name": "No name"}, {"email": "jane@doe.invalid"}, {"email": "joe@doe.invalid"}]}

It seems that attrs organise them on initialisation and because group-id & name have a default value, I am unable to place it at the top.

Is there a way to instruct the order?

2 Answers2

0

Which Python version? As of Python 3.7+ dictionaries are insertion ordered so asdict should respect the order of the fields as you provided them.

You could also change the dict_factory arg of attr.asdict to use collections.OrderedDict to enforce this otherwise.

Cory Kramer
  • 114,268
  • 16
  • 167
  • 218
  • I've updated the issue. My problem is that fields with default values have to go below fields without default values. So they don't look in order even in the class. I wondered if `attrs` would have a way to instruct the order/format – user18140022 Aug 10 '22 at 14:59
0

Do you want to sort your keys in the end? You can do it by passing sort_keys=True. For example:

import json
print(
    json.dumps(
        {"users": [
            {"email": "jane@doe.invalid"},
            {"email": "joe@doe.invalid"}
        ],
            "group-id": "a9fc0c10-125f-4c65-a901-ac16e3b57bc7"},
        sort_keys=True
    )
)

Output:

{"group-id": "a9fc0c10-125f-4c65-a901-ac16e3b57bc7", "users": [{"email": "jane@doe.invalid"}, {"email": "joe@doe.invalid"}]}
funnydman
  • 9,083
  • 4
  • 40
  • 55