Pydantic: Storing attributes that are not part of the model (equivalent of JsonExtensionData in C#)
Question:
I’m using pydantic to load data from a json structure into a MyModel
instance (see example below). Sometimes the JSON data come with extra keys which are not defined in the class MyModel
. Anyways I’d like have those data accessible in the deserialized MyModel instance somehow.
Minimal Working Example:
from pydantic import BaseModel
class MyModel(BaseModel):
"""
MyModel has two attributes: foo and bar
"""
foo: str
bar: int
my_json = r'{"foo":"foo value", "bar": 42, "baz": "something else"}'
# my_json has the attributes of MyModel + some extra key/value pair(s): key 'baz' in this case
my_model = MyModel.parse_raw(my_json) # I deserialize it
assert hasattr(my_model, "baz") is True # or something similar
In this example: Is there any way to find the "baz": "something else"
key value pair in the deserialized my_model
instance?
I know this behaviour exists in other Frameworks e.g. in C#/.NET as JsonExtensionData
:
… any properties that do not have a matching member are added to that [annotated] dictionary during deserialization and written during serialization.
Is there something similar for pydantic?
Answers:
Yes. That is what the extra
setting in the model config is for. By default it is set to ignore
. You can set it to allow
:
from pydantic import BaseModel
class MyModel(BaseModel):
foo: str
bar: int
class Config:
extra = "allow"
if __name__ == "__main__":
my_json = '{"foo":"foo value", "bar": 42, "baz": "something else"}'
my_model = MyModel.parse_raw(my_json)
assert hasattr(my_model, "baz")
print(my_model) # foo='foo value' bar=42 baz='something else'
PS: It may be worth mentioning that no static type checker will be able to infer that this particular MyModel
instance has a baz
attribute. That means no auto-suggestion for my_model.baz
from your IDE and so on. But I think that is obvious.
I’m using pydantic to load data from a json structure into a MyModel
instance (see example below). Sometimes the JSON data come with extra keys which are not defined in the class MyModel
. Anyways I’d like have those data accessible in the deserialized MyModel instance somehow.
Minimal Working Example:
from pydantic import BaseModel
class MyModel(BaseModel):
"""
MyModel has two attributes: foo and bar
"""
foo: str
bar: int
my_json = r'{"foo":"foo value", "bar": 42, "baz": "something else"}'
# my_json has the attributes of MyModel + some extra key/value pair(s): key 'baz' in this case
my_model = MyModel.parse_raw(my_json) # I deserialize it
assert hasattr(my_model, "baz") is True # or something similar
In this example: Is there any way to find the "baz": "something else"
key value pair in the deserialized my_model
instance?
I know this behaviour exists in other Frameworks e.g. in C#/.NET as JsonExtensionData
:
… any properties that do not have a matching member are added to that [annotated] dictionary during deserialization and written during serialization.
Is there something similar for pydantic?
Yes. That is what the extra
setting in the model config is for. By default it is set to ignore
. You can set it to allow
:
from pydantic import BaseModel
class MyModel(BaseModel):
foo: str
bar: int
class Config:
extra = "allow"
if __name__ == "__main__":
my_json = '{"foo":"foo value", "bar": 42, "baz": "something else"}'
my_model = MyModel.parse_raw(my_json)
assert hasattr(my_model, "baz")
print(my_model) # foo='foo value' bar=42 baz='something else'
PS: It may be worth mentioning that no static type checker will be able to infer that this particular MyModel
instance has a baz
attribute. That means no auto-suggestion for my_model.baz
from your IDE and so on. But I think that is obvious.