How to decode json with reserved name as key using json_dataclass? - python

I am trying to decode a json I received from an api using dataclass_json from the dataclasses_json module, however one of the json fields is called class which is a python reserved keyword. How can I define them?
{'some_var': False,
'class': '/12345.jpg'}
I tried this
#dataclass_json
#dataclass
class Media:
some_var: str
class: str ### error because class is a reserved keyword
parsedObject = Media.from_json(jsonString)
but get an error due to 'class' being a reserved keyword.

Specify the original field name as a field_name and name your class property differently:
from dataclasses import dataclass, field
from dataclasses_json import config, dataclass_json
#dataclass_json
#dataclass
class Media:
some_var: str
the_class: str = field(metadata=config(field_name="class"))
Check out the docs, scroll down to "Encode or decode using a different name".

Related

python data class default value for str to None

I have a dataclass like this:
from dataclasses import dataclass
#dataclass
class DataClassCard:
rank: str = None
suit: str
I am getting an error saying:
TypeError: non-default argument 'suit' follows default argument
Is there anyway to set this default value?
Finally calling:
queen_of_hearts = DataClassCard(suit = 'a')
queen_of_hearts.rank
Fields with a default value must come after any fields without a default. Just put suit above

Python typing: define type of the classvar based on another var

Is it possible to define type of the python class field based on another field?
Something like this:
from dataclasses import dataclass
from typing import ClassVar
#dataclass
class A:
a: str
#dataclass
class B(A):
b: str
#dataclass
class UseA:
field_cls: ClassVar[type] = A
field: A # <-- here should be something other, not just "A"
class UseB(UseA):
field_cls = B
def print_b(self) -> None:
print(self.field.b) # Here mypy says that "A has no attribute b"
If I'll run mypy --strict on this code I'll get the error: "A" has no attribute "b".
I need to define the type of "field" dynamically by another field "field_cls" so type checkers like mypy and my IDE (vscode) have to understand the right type of the UseB.field

Either of the two Pydantic attributes should be optional

I want validate a payload schema & I am using Pydantic to do that. The class created by inheriting Pydantic's BaseModel is named as PayloadValidator and it has two attributes, addCustomPages which is list of dictionaries & deleteCustomPages which is a list of strings.
class NestedCustomPages(BaseModel):
"""This is the schema for each custom page."""
html: str
label: str
type: int
class PayloadValidator(BaseModelWithContext):
"""This class defines the payload load schema and also validates it."""
addCustomPages: Optional[List[NestedCustomPages]]
deleteCustomPages: Optional[List[str]]
I want to declare either of the attributes of class PayloadValidator as optional. I have tried looking for the solution for this but couldn't find anything.
There was a question on this a while ago on the pydantic Github page: https://github.com/samuelcolvin/pydantic/issues/506. The conclusion there includes a toy example with a model that requires either a or b to be filled by using a validator:
from typing import Optional
from pydantic import validator
from pydantic.main import BaseModel
class MyModel(BaseModel):
a: Optional[str] = None
b: Optional[str] = None
#validator('b', always=True)
def check_a_or_b(cls, b, values):
if not values.get('a') and not b:
raise ValueError('Either a or b is required')
return b
mm = MyModel()

How to use python keywords in model defing with Pydantic?

I want to define a model like this:
class Item(BaseModel):
class: str
pass: float
Since "class" and "pass" are python keywords this will fail.
Use marshmallow can do this by using data_key:
class Item(Schema):
class_ = fields.String(data_key="class")
pass_ = fields.Float(data_key="pass")
Does pydantic has something like "data_key" or there are other ways to achieve the same goal?Thanks for answering
I can give you another option.
class Item(BaseModel):
class_: str
pass_: float
class Config:
fields = {
'class_': 'class'
'pass_': 'pass'
}

How to cast a variable to a dataclass type?

I want to use the function fields from the dataclasses module but my IDE keeps warning me that it should be only used on dataclasses (classes or instances). I know it is possible to ignore the warning, but I would like to cast my variable into a dataclass type, as it is more readable and IDE-compatible.
A brief example:
from dataclasses import fields
all_fields = fields(some_instance) # Here I get a warning
Context:
I want to write a "mixin" class to add type-enforcing on my dataclasses. Example:
from typing import Any
from dataclasses import fields, Field
class TypedDCMixin:
def __post_init__(self):
self._check_fields_types()
def _check_fields_types(self):
for field in fields(self): # HERE I get the warning from my IDE
field_value = getattr(self, field.name)
self._check_field_type(field, field_value)
def _check_field_type(self, field: Field, field_value: Any):
# whatever
pass
The same warning would arise from any other context where dataclasses.fields is used with an argument which is not known to be a dataclass.
I usually avoid type warnings like that by using the function typing.cast, but there is no DataclassType for me to do cast(DataclassType, self) at the warned line.
Hence my question: How to cast a variable to a dataclass type?
Using cast with the dataclass decorator works.
Modifying the original example to add the casting:
from typing import Any, cast
from dataclasses import fields, Field, dataclass
class TypedDCMixin:
def __post_init__(self):
self._check_fields_types()
def _check_fields_types(self):
for field in fields(cast(dataclass, self)): # Here the casting is used
field_value = getattr(self, field.name)
self._check_field_type(field, field_value)
def _check_field_type(self, field: Field, field_value: Any):
# whatever
pass

Categories