Home > front end >  Dictionaries in FastAPI BaseModels and how to send the right json body
Dictionaries in FastAPI BaseModels and how to send the right json body

Time:08-13

I am currently struggling to define a base model correctly displaying the data I want to send to it using postman's "raw body" (type set to JSON).

I want to send a body looking something like this:

{
    "a": [
        {
            "text": "text",
            "language": "en",
            "entities": [
                { "d": "g" },
                { "e": "h" },
                { "f": "i" }
            ]
        },
        {
            "text": "another text",
            "language": "en",
            "entities": [
                { "d": "z" }
            ]
        }
    ], 
    "b": [
        {
            "text": "more texts",
            "language": "en",
            "entities": [
                { "d": "r" },
                { "e": "t" },
                { "f": "z" }
            ]
        }
    ],
    "c": ["d", "e", "f"]
}

My endpoint in fastapi looks like this:

@app.post("/json")
def method(a: AModel, b: BModel, c: CModel):
  # code

and the BaseModels are:

class Input(BaseModel):
    text: str = Field (
        title="A text", example= "text"
    )
    language: str = Field (
        default=None, title="A language string", max_length=2, example="en"
    )
    entities: Dict[str, str] = Field (
        default=None, title="xxx.", 
        example= [{"d": "x"}, {"f": "y"}]
    )

    class Config:
        orm_mode=True

class CModel (BaseModel):
    c: List[str] = Field (
        title="xxx.", example= ["d", "e", "f"]
    )

class BModel (BaseModel):
    b: List[Input] = Field (
        title="yyy."
    )

class AModel (BaseModel):
    a: List[Input] = Field (
        title="zzz."
    )

However, sending the data to postman returns:

{
    "detail": [
        {
            "loc": [
                "body",
                "trainingdata"
            ],
            "msg": "value is not a valid dict",
            "type": "type_error.dict"
        },
        {
            "loc": [
                "body",
                "testingdata"
            ],
            "msg": "value is not a valid dict",
            "type": "type_error.dict"
        },
        {
            "loc": [
                "body",
                "entities"
            ],
            "msg": "value is not a valid dict",
            "type": "type_error.dict"
        }
    ]
}

(I am aware AModel and BModel have the same structure)

Now, I wanted to ask how I need to adjust my BaseModels to represent the structure I have shown in my initial body. I have seen people with similar issues but couldn't quite pinpoint it in my case.

Can anyone help?


EDIT: I forgot to mention that I cannot hardcode d, e and f into my BaseModel as these are just examples and I can't ever know for sure which keys the values there have.

CodePudding user response:

entities should be List[Dict[str, str]] and your route method should be as

class Combo(AModel, BModel, CModel):
    ...


@app.post("/")
def method(combo: Combo):
    return {
        "combo": combo
    }
  • Related