question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

How to have multiple str in body with an example for each of these str (while typing those value as string)

See original GitHub issue

First Check

  • I added a very descriptive title to this issue.
  • I used the GitHub search to find a similar issue and didn’t find it.
  • I searched the FastAPI documentation, with the integrated search.
  • I already searched in Google “How to X in FastAPI” and didn’t find any information.
  • I already read and followed all the tutorial in the docs and didn’t find an answer.
  • I already checked if it is not related to FastAPI but to Pydantic.
  • I already checked if it is not related to FastAPI but to Swagger UI.
  • I already checked if it is not related to FastAPI but to ReDoc.

Commit to Help

  • I commit to help with one of those options 👆

Example Code

from fastapi import FastAPI, Body
from pydantic import BaseModel

app = FastAPI()


@app.post("/one_body")
def one_body(
    sentence_1: str = Body(
        default=None,
        example="This should works fine",
    ),
):
    return "'I'm one_body"


@app.post("/only_body")
def only_body(
    sentence_1: str = Body(
        default=None,
        example="some example value (1)",
    ),
    sentence_2: str = Body(
        default=None,
        example="some example value (2)",
    ),
):
    return "'I'm only_body"


class Sentence1(BaseModel):
    sentence_2: str

    class Config:
        schema_extra = {
            "example": "This is the first sentence that I have hard-coded",
        }

class Sentence2(BaseModel):
    sentence_2: str

    class Config:
        schema_extra = {
            "example": "This is the second sentence that I have hard-coded",
        }


@app.post("/with_base_model")
def with_base_model(
    sentence_1: Sentence1 = Body(
        default=None,
        example=Sentence1.Config.schema_extra["example"],
    ),
    sentence_2: Sentence2 = Body(
        default=None,
        # example=Sentence2.Config.schema_extra["example"], # NOTE: volontarely comment this line to show that it changes nothing
    ),
):
    return "'I'm only_body"

Description

I’m trying to find a way to :

  • create a route with two str params required in the body
  • those params being typed as str
  • providing an example value for those two str

But seems that if we provide two value in the body we must use BaseModel (cf) to describe it example value, however if we do that the param will no longer be typed as an str but as an object.

How can I create a route requiring two str in the body while providing an example for those two str and still have those values typed as str?

In the example code I create three routes :

  1. /one_body to show that we can provide an example when there is only one value in the body
  2. /only_body to show that when provide two values in the body we can no longer provide an example
  3. /with_base_model to show that when use BaseModel to provide an example, the value is no longer typed as an str
/openapi.json
{
  "openapi": "3.0.2",
  "info": {
    "title": "FastAPI",
    "version": "0.1.0"
  },
  "paths": {
    "/one_body": {
      "post": {
        "summary": "One Body",
        "operationId": "one_body_one_body_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "title": "Sentence 1",
                "type": "string"
              },
              "example": "This should works fine"
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/only_body": {
      "post": {
        "summary": "Only Body",
        "operationId": "only_body_only_body_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Body_only_body_only_body_post"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/with_base_model": {
      "post": {
        "summary": "With Base Model",
        "operationId": "with_base_model_with_base_model_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Body_with_base_model_with_base_model_post"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Body_only_body_only_body_post": {
        "title": "Body_only_body_only_body_post",
        "type": "object",
        "properties": {
          "sentence_1": {
            "title": "Sentence 1",
            "type": "string"
          },
          "sentence_2": {
            "title": "Sentence 2",
            "type": "string"
          }
        }
      },
      "Body_with_base_model_with_base_model_post": {
        "title": "Body_with_base_model_with_base_model_post",
        "type": "object",
        "properties": {
          "sentence_1": {
            "$ref": "#/components/schemas/Sentence1"
          },
          "sentence_2": {
            "$ref": "#/components/schemas/Sentence2"
          }
        }
      },
      "HTTPValidationError": {
        "title": "HTTPValidationError",
        "type": "object",
        "properties": {
          "detail": {
            "title": "Detail",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ValidationError"
            }
          }
        }
      },
      "Sentence1": {
        "title": "Sentence1",
        "required": [
          "sentence_2"
        ],
        "type": "object",
        "properties": {
          "sentence_2": {
            "title": "Sentence 2",
            "type": "string"
          }
        },
        "example": "This is the first sentence that I have hard-coded"
      },
      "Sentence2": {
        "title": "Sentence2",
        "required": [
          "sentence_2"
        ],
        "type": "object",
        "properties": {
          "sentence_2": {
            "title": "Sentence 2",
            "type": "string"
          }
        },
        "example": "This is the second sentence that I have hard-coded"
      },
      "ValidationError": {
        "title": "ValidationError",
        "required": [
          "loc",
          "msg",
          "type"
        ],
        "type": "object",
        "properties": {
          "loc": {
            "title": "Location",
            "type": "array",
            "items": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "integer"
                }
              ]
            }
          },
          "msg": {
            "title": "Message",
            "type": "string"
          },
          "type": {
            "title": "Error Type",
            "type": "string"
          }
        }
      }
    }
  }
}

Operating System

Linux

Operating System Details

No response

FastAPI Version

0.79.0

Python Version

Python 3.8.10

Additional Context

No response

Issue Analytics

  • State:open
  • Created a year ago
  • Comments:8 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
Thytucommented, Aug 23, 2022

@JarroVGIT This is my current stat of understanding regarding the code base :

  1. get_param_field is called by get_dependant (for each signature_params) which call create_response_field.

  2. create_response_field returns field that contains the example value (field.field_info.example) for the parameter.

  3. create_response_field is also called to create the route schema in get_body_field returning final_field.

  4. final_field does not seems to contain any informations relating to the body parameters, and so to the example values. (Does I miss-understand this part? If so, where does the information concerning the body parameters are provided and stored within final_field?)

If final_field does indeed not contains any informations relating to the body parameters I need to search wether this bug is due to : A. The ApiRoute not providing those informations when creating the openapi.json B. The ApiRoute does provide those informations when creating the openapi.json but there are not used.

On the contrary, if final_field contains the informations relating to the body parameters (and thus the example values) I need to verify that those values are keep in final_field.

I have also few questions for you:

  • Where does the openapi.json is create ?
  • Is final_field used to create the schema for each param in the openapi.json or is only used to create the path schema and self.dependencies is used to create those schema?

I hope my explanations and understanding are not too messy. Thanks for your feedbacks.

1reaction
JarroVGITcommented, Aug 17, 2022

Body() is a special function that returns an instance of class Body, the same goes for Form() (which returns an instance of Form). The class Form is a subclass of Body, so I would expect the same behaviour indeed.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Creating multiline strings in JavaScript - Stack Overflow
As the first answer mentions, with ES6/Babel, you can now create multi-line strings simply by using backticks: const htmlString = `Say hello to...
Read more >
typing — Support for type hints — Python 3.11.1 documentation
The Python runtime does not enforce function and variable type annotations. ... async def on_update(value: str) -> None: # Body callback: Callable[[str], ...
Read more >
Useful string methods - Learn web development | MDN
Concatenate the two new variables and a string literal to make the final string. Change the value of the result variable to the...
Read more >
A Guide to the Newer Python String Format Techniques
The string .format() method; The formatted string literal, or f-string. You'll learn about these formatting techniques in detail and add them to ...
Read more >
Query Parameters and String Validations - FastAPI
The query parameter q is of type Union[str, None] (or str | None in Python 3.10), ... And now use it as the...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found