Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pydantic create model for list with nested dictionary

I have a body looks like this:

{
    "data": [
      {
        "my_api": {
          "label": "First name",
          "value": "Micheal"
        }
      },
      {
        "my_api": {
          "label": "Last name",
          "value": [
            "Jackson"
          ]
        }
      },
      {
        "my_api": {
          "label": "Favourite colour",
          "value": "I don't have any"
        }
      }
    ]
  }

This is my model.py so far:

class DictParameter(BaseModel): # pylint: disable=R0903
    """
    `my_api` children
    """
    label: Optional[str]
    value: Optional[str]


class DataParameter(BaseModel): # pylint: disable=R0903
    """
    `data` children
    """
    my_api: Optional[dict]  # NOTE: Future readers, this incorrect reference is part of the OP's Q


class InputParameter(BaseModel): # pylint: disable=R0903
    """
    Takes predefined params
    """
    data: Optional[List[DataParameter]]

In main.py:

from model import InputParameter

@router.post("/v2/workflow", status_code=200)
def get_parameter(user_input: InputParameter):
    """
    Version 2 : No decoding & retrieve workflow params
    """
    data = user_input.data

    print(data)

Output:

[DataParameter(my_api={'label': 'First name', 'value': 'Micheal'}), DataParameter(my_api={'label': 'Last name', 'value': ['Jackson']}), DataParameter(my_api={'label': 'Favourite colour', 'value': "I don't have any"})]

I want to access the value inside my_api key. But I keep getting type error. I'm not sure how to access List of dictionary with nested child. Plus, the value of value can be str or array. It is dynamic.

Is there any other way of doing this?

like image 263
user6308605 Avatar asked Dec 07 '25 02:12

user6308605


1 Answers

Plus, the value of value can be str or array. It is dynamic.

What you currently have will cast single element lists to strs, which is probably what you want. If you want lists to stay as lists, use:

from Typing import Union

class DictParameter(BaseModel):
    Value: Union[str, list[str]]

Unless you have the good luck to be running python 3.10, on which case str | list[str] is equivalent.

However, you do not actually use this model! You have my_api: Optional[dict] not my_api: Optional[DictParameter], so your current output is a plain old dict, and you need to do data[0].my_api["value"]. Currently this returns a str or a list, which is probably the problem. I suspect, though, that you meant to use the pydantic schema.

Note that data is a list: if you want all the values you need to iterate, something like

apis = [x.my_api for x in data]
like image 56
2e0byo Avatar answered Dec 08 '25 16:12

2e0byo