When using Union type with pydantic, combine it with Literal

We have implemented a chatbot, which is "save the user's past request contents in Redis and refer to it as needed to use it for bot reply". Specifically, the specifications and programs are as follows.

  1. Cast the json of the user's request to Request type and use it
  2. In Redis, convert pydantic type to json, save it as a string, and cast it to Request type when retrieving
  3. Output the json to the log at the same time
from __future__ import annotations
from typing import Union, Optional
from typing_extensions import Literal
from .event import EventData


class Request(BaseModel):
    user_id: str
    session_id: str
    command: Union[MessageCommand, ButtonCommand]


class MessageCommand(BaseModel):
    """When a free text message is entered"""
    type: Literal["message"]
    message: Optional[str]
    is_first: bool = False


class ButtonCommand(BaseModel):
    """When the button is pressed"""
    type: Literal["button"]
    event: Optional[EventData]
    is_first: bool = False


Request.update_forward_refs()

Initially, I didn't have a property for type, and when retrieving from Redis, json, which should be ButtonCommand, was accidentally cast as an empty MessageCommand. When using the default value or ʻOptional`, you can cast even the wrong json.

By specifying a fixed character string with Literal in the type property, you can surely specify the conversion destination.

reference

Recommended Posts

When using Union type with pydantic, combine it with Literal
When using optparse with iPython
When using MeCab with virtualenv python
Precautions when using six with Python 2.5
When to_csv with Pandas, it became line by line
About WARNING when packaging with pyinstaller using pyocr
Secret key generation when using EncryptedCookieStorage with aiohttp_session
How to deal with SessionNotCreatedException when using Selenium
What are you using when testing with Python?
How to deal with "Type Error: No matching signature found" error when using pandas fillna