'How do you handle mapping camelCase json to snake_case python dataclass field names?

I'm using Python to interact with a web api, where the keys in the json responses are in camelCase. My python models are dataclasses, who's field names are snake_case. When I convert from json to model and vise-versa, the names obviously do not match up.

For reference, I'm using the asdict function to convert my models to json.

def to_json(self):
  return asdict(
    self, 
    dict_factory=lambda _fields: {
      key: value for (key, value) in _fields if value is not None
    }
  )

The code that converts from json to model is slightly more complicated, but also relies on the field names for mapping to the json keys. Both of the conversions are generic enough that it works with all my models, without having to create converters for each individual model (30 or so).

In this case, is it common practice to use cameCase for my model field names (even though it doesn't conform to standard naming practice)?

I cannot modify the api, for better or worse the key names will always be in camelCase.



Solution 1:[1]

One option could be to use the dataclass-wizard library, which supports automatic mapping of camelCase (or PascalCase or spinal-case) to snake_case, which is convention in Python. It should also end up being a little faster than something like marshmallow, though honestly I haven't tested this out myself.

A simplified example, taken from the docs:

from __future__ import annotations
from dataclasses import dataclass, field
from dataclass_wizard import JSONWizard

@dataclass
class MyClass(JSONWizard):
    my_str: str | None
    is_active_tuple: tuple[bool, ...]
    list_of_int: list[int] = field(default_factory=list)

string = """
{
  "my_str": 20,
  "ListOfInt": ["1", "2", 3],
  "isActiveTuple": ["true", false, 1]
}
"""

instance = MyClass.from_json(string)
print(f'{instance!r}')
# MyClass(my_str='20', is_active_tuple=(True, False, True), list_of_int=[1, 2, 3])
print(instance.to_json())
# '{"myStr": "20", "isActiveTuple": [true, false, true], "listOfInt": [1, 2, 3]}'
assert instance == MyClass.from_dict(instance.to_dict())  # True

The dataclass-wizard library can be installed with pip:

$ pip install dataclass-wizard

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1