简体   繁体   中英

Obtain JSON from FastAPI using Pydantic Nested Models

The following code receives some JSON that was POSTed to a FastAPI server. FastAPI makes it available within a function as a Pydantic model. My example code processes it by writing a file. What I don't like (and it seems to be side-effect of using Pydantic List) is that I have to loop back around to get some usable JSON.

How can I do this without looping?

I feel it must be possible because return images just works.

from typing import List

from fastapi import FastAPI
from pydantic import BaseModel
import json

app = FastAPI()

class Image(BaseModel):
    url: str
    name: str

@app.post("/images/multiple/")
async def create_multiple_images(images: List[Image]):
  #return images             # returns json string
  #print(images)             # prints an Image object
  #print(images.json())      # AttributeError: 'list' object has no attribute 'json'
  #print(json.dumps(images)) # TypeError: Object of type Image is not JSON serializable
  img_data = list()          # does it really have to be this way?
  for i in images:
    img_data.append(i.dict())
  with open('./images.json', 'w') as f:  
    json.dump(img_data, f, indent=2)

'''
curl -v -d '[{"name":"wilma","url":"http://this.com"},{"name":"barney","url":"http://that.com"}]' http://localhost:8000/images/multiple/
'''

The example is expanded from the FastAPI docs

To dump a list of model objects without loops, pydantic provides the ability to define a model with a custom root type .

Here is a small example of how it looks:

class Image(BaseModel):
    url: str
    name: str


class Images(BaseModel):
    __root__: List[Image]


images_raw = '[{"url":"url1", "name":"name1"}, {"url":"url2", "name":"name2"}]'
images = parse_raw_as(Images, images_raw)

with open('./images.json', 'w') as f:
    f.write(images.json(indent=2))

And the definition of your path operation would look like this:

@app.post("/images/multiple/")
async def create_multiple_images(images: Images):
    with open('./images.json', 'w') as f:
        f.write(images.json(indent=2))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM