title: supporting both form and json encoded bodys with FastAPI
body: <p>I've been using <a href="https://fastapi.tiangolo.com/" rel="noreferrer">FastAPI</a> to create an HTTP based API.  It currently supports JSON encoded parameters, but I'd also like to support <code>form-urlencoded</code> (and ideally even <code>form-data</code>) parameters at the same URL.</p>
  
  <p>Following on <a href="https://stackoverflow.com/a/60670614/1358308">Nikita's answer</a> I can get separate urls working with:</p>
  
  <pre><code>from typing import Optional
  from fastapi import FastAPI, Body, Form, Depends
  from pydantic import BaseModel
  
  class MyItem(BaseModel):
      id: Optional[int] = None
      txt: str
  
      @classmethod
      def as_form(cls, id: Optional[int] = Form(None), txt: str = Form(...)) -&gt; 'MyItem':
          return cls(id=id, txt=txt)
  
  app = FastAPI()
  
  @app.post("/form")
  async def form_endpoint(item: MyItem = Depends(MyItem.as_form)):
      print("got item =", repr(item))
      return "ok"
  
  @app.post("/json")
  async def json_endpoint(item: MyItem = Body(...)):
      print("got item =", repr(item))
      return "ok"
  </code></pre>
  
  <p>and I can test these using <code>curl</code> by doing:</p>
  
  <pre class="lang-sh prettyprint-override"><code>curl -X POST "http://localhost:8000/form" -d 'txt=test'
  </code></pre>
  
  <p>and</p>
  
  <pre class="lang-sh prettyprint-override"><code>curl -sS -X POST "http://localhost:8000/json" -H "Content-Type: application/json" -d '{"txt":"test"}'
  </code></pre>
  
  <p>It seems like it would be nicer to have a single URL that accepts both content-types and have the model parsed out appropriately.  But the above code currently fails with either:</p>
  
  <pre><code>{"detail":[{"loc":["body","txt"],"msg":"field required","type":"value_error.missing"}]}
  </code></pre>
  
  <p>or</p>
  
  <pre><code>{"detail":"There was an error parsing the body"}
  </code></pre>
  
  <p>if I post to the "wrong" endpoint, e.g. form encoding posted to <code>/json</code>.   </p>
  
  <p>For bonus points; I'd also like to support <code>form-data</code> encoded parameters as it seems related (my <code>txt</code> can get rather long in practice), but might need to turn it into another question if it's sufficiently different.</p>