Search code examples
pythonpydantic

Define a class (e.g. dataclass or Pydantic BaseModel or TypedDict) whose fields are defined by a collection of strings


Suppose I have a collection of strings defined as a StrEnum:

class ValidNames(StrEnum):
    OLLY = auto()
    ADAM = auto()
    ANNA = auto()

I want to define a class, ideally with Pydantic (for type verification and conversion) that looks like this:

class Assignment(pydantic.BaseModel):
    olly: int = 0
    adam: int = 0
    anna: int = 0

And I want to be able to take external JSON data like this:

external_data = {"olly": 14, "anna": 3}
this_assignment = Assignment(**external_data)

However, I don't want to have to explicitly define the fields of Assignment; I want it to be defined by the values of ValidNames because I don't want to change two bits of code every time the members of ValidNames change (or are added or deleted), and for other reasons. Is there a way to do this, with or without Pydantic?

Basically I just want a dict[ValidNames, pydantic.NonNegativeInt] but as a class (with default value 0 for each field) and not a dict. Ideally a Pydantic class.


Solution

  • Pydantic supports dynamic model creation.

    from enum import StrEnum, auto
    from pydantic import create_model
    
    
    class ValidNames(StrEnum):
        OLLY = auto()
        ADAM = auto()
        ANNA = auto()
    
    
    Assignment = create_model(
        'Assignment',
        **{vn.value: (int, 0) for vn in ValidNames}
    )