I have two endpoints below, one that accepts two integers and another that accepts tow lists of integers.
I also have two post requests that I am making using Python requests
. The request for the list of ints endpoint works fine, but the one that just accepts the two ints does not.
I know that if I pass the two ints in the URL (i.e, the query string), the endpoint will work. However, could you tell me why it doesn't work when passed as JSON?
endpoints.py
from fastapi import FastAPI
app = FastAPI()
@app.post('/ints')
def post_int(x: int, y: int):
return x, y
@app.post('/lists')
def post_list(x: list[int], y: list[int]):
return x, y
requests.py
import requests
r = requests.post('http://127.0.0.1:8000/ints', json={'x': 1, 'y': 2})
print(r.json()) # returns an error saying that x and y are missing
r = requests.post('http://127.0.0.1:8000/ints?x=1&y=2')
print(r.json()) # returns the two ints
r = requests.post('http://127.0.0.1:8000/lists', json={'x': [1, 2, 5], 'y': [1, 2, 3]})
print(r.json()) # returns the two lists
To start server, run "fastapi dev /path/to/endpoints.py" in terminal. Run requests.py in another terminal for output.
I have two endpoints below, one that accepts two integers and another that accepts tow lists of integers.
I also have two post requests that I am making using Python requests
. The request for the list of ints endpoint works fine, but the one that just accepts the two ints does not.
I know that if I pass the two ints in the URL (i.e, the query string), the endpoint will work. However, could you tell me why it doesn't work when passed as JSON?
endpoints.py
from fastapi import FastAPI
app = FastAPI()
@app.post('/ints')
def post_int(x: int, y: int):
return x, y
@app.post('/lists')
def post_list(x: list[int], y: list[int]):
return x, y
requests.py
import requests
r = requests.post('http://127.0.0.1:8000/ints', json={'x': 1, 'y': 2})
print(r.json()) # returns an error saying that x and y are missing
r = requests.post('http://127.0.0.1:8000/ints?x=1&y=2')
print(r.json()) # returns the two ints
r = requests.post('http://127.0.0.1:8000/lists', json={'x': [1, 2, 5], 'y': [1, 2, 3]})
print(r.json()) # returns the two lists
To start server, run "fastapi dev /path/to/endpoints.py" in terminal. Run requests.py in another terminal for output.
Share Improve this question edited Mar 14 at 5:35 Chris 35.5k10 gold badges104 silver badges251 bronze badges asked Mar 13 at 15:46 JayJay 591 silver badge7 bronze badges 3 |1 Answer
Reset to default 0could you tell me why it doesn't work when passed as JSON?
When you register a route with
@app.post('/ints')
def post_int(x: int, y: int):
return x, y
in FastApi, the route is analyzed and added in
decorator (routing.py)
add_api_route (routing.py)
__init__ (routing.py)
get_dependant (dependencies/utils.py)
analyze_param (dependencies/utils.py)
Near the end of analyze_param
, you can find
elif field_info is None and depends is None:
default_value = value if value is not inspect.Signature.empty else RequiredParam
if is_path_param:
# We might check here that `default_value is RequiredParam`, but the fact is that the same
# parameter might sometimes be a path parameter and sometimes not. See
# `tests/test_infer_param_optionality.py` for an example.
field_info = params.Path(annotation=use_annotation)
elif is_uploadfile_or_nonable_uploadfile_annotation(
type_annotation
) or is_uploadfile_sequence_annotation(type_annotation):
field_info = params.File(annotation=use_annotation, default=default_value)
elif not field_annotation_is_scalar(annotation=type_annotation):
field_info = params.Body(annotation=use_annotation, default=default_value)
else:
field_info = params.Query(annotation=use_annotation, default=default_value)
https://github/fastapi/fastapi/blob/master/fastapi/dependencies/utils.py#L460
There you can see that scalar parameters have field info type query. Lists aren't scalar values and have field info type body.
list
parameters as body data by default. To use them as query params instead, you need to explicitly useQuery
– Chris Commented Mar 13 at 17:52