dataclass-wizard
dataclass-wizard copied to clipboard
Avoid any transformation on key names
- Dataclass Wizard version: 0.22.2
- Python version: 3.10.6
- Operating System: Pop!_OS 22.04 LTS
Description
I found that by default, when serializing a dataclass, all the key names are changed to camelCase. This was surprising to me. By reading the documentation I found that it is possible to change this, but I could not find documentation on what alternative behaviors are supported (i.e., what values of key_transform
are supported). I spent some time reading the source code, and found the following:
https://github.com/rnag/dataclass-wizard/blob/e3fe0760422613eaf79e0236840a50f27caec064/dataclass_wizard/enums.py#L16-L29
Based on this code it seems the supported behaviors are to transform into camelCase, PascalCase, lisp-case, and snake_case. However, what I actually want is for no transformation whatsoever to happen. Is this possible?
Ideally, I want to be able to inhibit the key transformation entirely, without having to modify all (or any) dataclasses in my application. Based on the design of other json/yaml libraries for Python, I would expect to be able to accomplish this by passing a keyword argument to the asdict
function, but as far as I can tell, this does not seem to be possible. Instead, one must globally modify the dataclass definition at runtime by invoking DumpMeta.bind_to
. This was also surprising to me.
The ask:
- It should be possible to disable key transformation, instead of just change it to a different transformation.
- It should be possible to accomplish with a keyword argument to
asdict
, without changing any dataclass definition either in code or at runtime. - It should be documented what are the possible ways to configure key transformation, and/or how to add your own (if this is supported).
I'm happy to implement a feature like this in a pull request and add tests, but have I missed some reason this would be a bad idea / did I miss documentation that explains it?
What I Did
I have dataclasses that look like this, no special meta annotations:
@dataclass
class Transaction:
date_posted: datetime
date_cleared: datetime
currency: str
amount: Decimal
Then I am converting them to json like this, ideally without date_posted
being changed to datePosted
:
print(json.dumps(dataclass_wizard.asdict(transaction), indent=2, default=str))
Of course, specifying SNAKE_CASE
as the transform is a workaround in this case, but really I do not want any transformation.
Adding
diff --git a/dataclass_wizard/enums.py b/dataclass_wizard/enums.py
index 1b9757e..4fb5356 100644
--- a/dataclass_wizard/enums.py
+++ b/dataclass_wizard/enums.py
@@ -27,6 +27,9 @@ class LetterCase(Enum):
# Converts strings (generally in camel case) to snake case.
# ex: `myFieldName` -> `my_field_name`
SNAKE = FuncWrapper(to_snake_case)
+ # Perfoms no conversion on strings.
+ # ex: `MY_FIELD_NAME` -> `MY_FIELD_NAME`
+ NONE = FuncWrapper(str)
def __call__(self, *args):
return self.value.f(*args)
and setting up the dataclass like
@dataclass
class MyDataclass(JSONWizard):
VAR_1: int
vAr__2: int
VAr3__: int
class _(JSONWizard.Meta):
key_transform_with_dump = "NONE"
data = """{
"VAR_1": 1,
"vAr__2": 2,
"VAr3__": 3
}
"""
foo = MyDataclass.from_json(data)
print("JSON -> Dataclass", foo)
print("Dataclass -> JSON", foo.to_json())
prints with no transformations
JSON -> Dataclass {
"VAR_1": 1,
"vAr__2": 2,
"VAr3__": 3
}
Dataclass -> JSON {"VAR_1": 1, "vAr__2": 2, "VAr3__": 3}
Hey @raxod502 and @cquick01, thanks for asking and contributing to this issue. I think the PR forgot to be linked but just adding it here -- #94 and I added a comment on there.
Seems like a simple change though, and I am ok with this, but once comment with justification is added I'm ok to go ahead and merge. I feel this could be a useful addition for others. Thanks!
Looks pretty good to me, I think the only thing missing now is documenting the existence of the feature!