3

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?

1 Answer 1

4

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"
        }
      }
    }
  }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.