Reputation: 10583
I am trying to load a yml file into a dict
, with pyyaml
, theloading process automatically loads proper types for me, e.g., yml file with content below:
key1: test
key2: 100
will be loaded into a dict
of {"key1": "test", "key2":100} where the type of key1's value is string
, and the type of key2's value is int
.
Now I want to dynamically create a class based on this dict
, basically a class that has the dict
keys as fields and dict
values as values as shown below:
class Test:
key1: str = "test"
key2: int = 100
I believe I can do something like below using Pydantic
:
Test = create_model('Test', key1=(str, "test"), key2=(int, 100))
However, as shown here, I have to manually tell create_model
what keys and types for creating this model. I wonder if there is a away to automatically use the items in the dict
to create model?
Upvotes: 3
Views: 4924
Reputation: 32273
Yes, for example, you could call create_model
recursively for dictionary items, passing keys and value types, the values themselves can become default values.
Example (not production ready):
from typing import Dict
from pydantic import create_model
test_dict = {'a': 12, 'nested': {'b': 'value', 'c': 1}}
def _make_model(v, name):
if type(v) is dict:
return create_model(name, **{k: _make_model(v, k) for k, v in v.items()}), ...
return type(v), v
def make_model(v: Dict, name: str):
return _make_model(v, name)[0]
model = make_model(test_dict, 'MyModel')
m = model.parse_obj(test_dict)
print(m)
print(model.schema_json(indent=2))
Output:
a=12 nested=nested(b='value', c=1)
{
"title": "MyModel",
"type": "object",
"properties": {
"a": {
"title": "A",
"default": 12,
"type": "integer"
},
"nested": {
"$ref": "#/definitions/nested"
}
},
"required": [
"nested"
],
"definitions": {
"nested": {
"title": "nested",
"type": "object",
"properties": {
"b": {
"title": "B",
"default": "value",
"type": "string"
},
"c": {
"title": "C",
"default": 1,
"type": "integer"
}
}
}
}
}
Upvotes: 4