How to define Pydantic Class for nested dictionary

Viewed 1013

How do we define a Pydantic Class Type for the following nested dictionary structure (with complicated strings as keys):

{ "inputs" : {
        "simpleStringName": <Simple_DateTime_Value>
        "simpleStringName2": {
        "Complicated|String|Name|with|Pipe|Characters" : <Simple-Int-Value>,
        "Complicated|String|Name2|with|Pipe|Characters" : <Simple-Int-Value2>
        }
    }
}

Pydantic needs to enforce the entire structure. That is simply this will not work:

class XYZ(BaseModel):
    inputs : Dict()

I want to enforce requests input format using Pydantic with fastAPI.

1 Answers

Something like this is probably what you're after

import datetime
from typing import Union, Dict
from pydantic import BaseModel

class XYZ(BaseModel):
    inputs: Dict[str, Union[datetime.datetime, Dict[str, int]]]
>>> XYZ(**{
...     "inputs" : {
...         "simpleStringName": datetime.datetime.utcnow(),
...         "simpleStringName2": {
...             "Complicated|String|Name|with|Pipe|Characters" : 3,
...             "Complicated|String|Name2|with|Pipe|Characters" : 4
...         }
...     }
... })
XYZ(inputs={'simpleStringName': datetime.datetime(2021, 11, 11, 16, 34, 21, 906156), 'simpleStringName2': {'Complicated|String|Name|with|Pipe|Characters': 3, 'Complicated|String|Name2|with|Pipe|Characters': 4}})

If you want to explicitly define the strings, you can use Pydantic's Constrained Types (here constr with a regex, but many options are available)
https://pydantic-docs.helpmanual.io/usage/types/#constrained-types

class XYZ(pydantic.BaseModel):
    inputs: Dict[
        pydantic.constr(regex="^[a-zA-Z\d]+$"),
        Union[
            datetime.datetime,
            Dict[
                pydantic.constr(regex="^[a-zA-Z\d\|]+$"),
                int
            ]
        ]
    ]
Related