pythonjsonfastapioptional-parameterskeyword-argument

How to pass **kwargs as params to FastAPI endpoint?


I have a function generating a dict template. This function consists of several generators and requires one parameter (i.e., carrier) and has many optional parameters (keyword arguments - **kwargs).

def main_builder(carrier, **params):
    output = SamplerBuilder(DEFAULT_JSON)
    output.generate_flight(carrier)
    output.generate_airline_info(carrier)
    output.generate_locations()
    output.generate_passengers()
    output.generate_contact_info()
    output.generate_payment_card_info()
    output.configs(**params)
    result = output.input_json
    return result 

# example of function call
examplex = main_builder("3M", proxy="5.39.69.171:8888", card=Visa, passengers={"ADT":2, "CHD":1}, bags=2)

I want to deploy this function to FastAPI endpoint. I managed to do it for carrier but how can I set **kwargs as params to the function?

@app.get("/carrier/{carrier_code}", response_class=PrettyJSONResponse) # params/kwargs??
async def get_carrier(carrier_code):
    output_json = main_builder(carrier_code)
    return airline_input_json

Solution

  • Using Pydantic Model

    Since your function "..has many optional parameters" and passengers parameter requires a dictionary as an input, I would suggest creating a Pydantic model, where you define the parameters, and which would allow you sending the data in JSON format and getting them automatically validated by Pydantci as well. Once the endpoint is called, you can use Pydantic's dict() method (Note: In Pydantic V2, dict() was replaced by model_dump()—see this answer for more details) to convert the model into a dictionary.

    Example

    from pydantic import BaseModel
    from typing import Optional
    
    class MyModel(BaseModel):
        proxy: Optional[str] = None
        card: Optional[str] = None
        passengers: Optional[dict] = None 
        bags: Optional[int] = None
    
    @app.post("/carrier/{carrier_code}")
    async def get_carrier(carrier_code: int, m: MyModel):
        return main_builder(carrier_code, **m.dict())  # In Pydantic V2, use **m.model_dump()
    

    Sending arbitrary JSON data

    In case you had to send arbitrary JSON data, and hence, pre-defining the parameters of an endpoint wouldn't be possible, you could use an approach similar to the one described in this answer (see Options 3 and 4), as well as this answer and this answer.