Fastapi: [BUG] TypeError: Object of type '_GenericAlias' is not JSON serializable

Created on 3 Jun 2020  路  8Comments  路  Source: tiangolo/fastapi

Describe the bug

I am unable to debug the issue with some of my model schemas (the traceback for this issue is not helpful). For context, I have a Base model that contains the relevant json_encoders for the non standard fields (datetime, ObjectId, etc), yet there is some pydantic field that isn't being translated.

The schemas uses the following EXTRA fields (from pydantic):

  • AnyUrl
  • Dict
  • SecretStr
  • Field
  • Union

Environment

  • OS: Linux
  • FastAPI Version 0.5.2
  • Python version: 3.7.4

Traceback

...
File "/usr/local/lib/python3.7/site-packages/pydantic/schema.py", line 503, in model_type_schema
f, by_alias=by_alias, model_name_map=model_name_map, ref_prefix=ref_prefix, known_models=known_models
File "/usr/local/lib/python3.7/site-packages/pydantic/schema.py", line 186, in field_schema
s['default'] = encode_default(field.default)
File "/usr/local/lib/python3.7/site-packages/pydantic/schema.py", line 725, in encode_default
return pydantic_encoder(dft)
File "/usr/local/lib/python3.7/site-packages/pydantic/json.py", line 59, in pydantic_encoder
raise TypeError(f"Object of type '{obj.__class__.__name__}' is not JSON serializable")
TypeError: Object of type '_GenericAlias' is not JSON serializable
question

Most helpful comment

Edit: It was a type from the typing_extensions library, specifically Literal. I just removed it and converted them into Enum based sub schemas, and it worked!

All 8 comments

Is it possible for you to provide a more complete example of how to reproduce the issue? E.g. a minimal app with a model and route that, when hit, will trigger the error?

From the information you gave, it looks like error has to do with Pydantic, and not anything specific to FastAPI. Does just calling pydantic_encoder on an instance of your class generate the exception?

I am working with multiple models, so I actually need some pointers on how I can pinpoint where the error might be. I understand that it鈥檚 a pydantic error, but is there any way of making the traceback a bit more verbose in terms of which model validation is actually failing? Or is there is a list of model (pydantic) fields that aren鈥檛 supported by the openAPI spec?

In looking at the error again, I did a search for _GenericAlias and it looks like that used in the internals of the typing module. So my guess is that somewhere you鈥檙e assigning a type to a field in Pydantic instead of using a type annotation (e.g. field = List instead of field: List).

That doesn鈥檛 help you narrow down _where_ the error is just what it might be.

When does this exception happen? When you start up the app or when you call a certain endpoint?

If on startup you could try commenting out some end points (or even better, whole routers if you use them) to narrow down the issue.

You could also navigate to the Pyndantic source in your environment and put in a breakpoint (if you鈥檙e using an IDE) or print statement.

File "/usr/local/lib/python3.7/site-packages/pydantic/schema.py", line 186 maybe?

Edit: It was a type from the typing_extensions library, specifically Literal. I just removed it and converted them into Enum based sub schemas, and it worked!

Thanks for the help here @dbanty ! :clap: :bow:

Thanks for reporting back and closing the issue @Pk13055 :+1:

Sorry to comment on a closed bug, but I have this same error but I don't use Literal anywhere in my code. I have tried to isolate the issue into a small project but the problem is not reproducible there. I am doing List[InviteePatch] in my route params, for some reason this is causing the issue. When I pull that model into a small project and add a route with the same signature /openapi.json renders fine. In my actual project using latest 1.6.1 Pydantic it fails. Any ideas?

@router.post("/surveys/{id}", response_model=List[Invitee])
async def post_for_survey(
        *,
        id: int,
        invitees_in: List[InviteePatch] = List[InviteePatch],
        logged_in: bool = Depends(validate_token),
        model_exists: bool = Depends(survey_service.survey_exists),
        db: Session = Depends(get_surveyor_db),
):
    invitee_response = await invitee_service.post_for_survey(db, id, invitees_in)
    await invitee_service.delete_old_invitees_for_survey(db, id, invitees_in)
    return invitee_response
class InviteePatch(BaseModel):
    unix_id: str = None
    proper_name: str = None
    email_address: str = None
    invite_hash: str = None
    tokens: dict = None

    class Config:
        orm_mode = True

The issue is using a generic from the typing module as a value instead of just a type hint. Specifically invitees_in: List[InviteePatch] = List[InviteePatch] is saying "assign this generic type to my variable if a value is not provided".

There are multiple ways the fix it but I assume you want an empty list as a default so you would do something like invitees_in: List[InviteePatch] = Body([]).

If you don't want the default and can make it a required param then just do invitees_in: List[InviteePatch]

Hmm, I see. Thanks so much!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

laith43d picture laith43d  路  3Comments

iwoloschin picture iwoloschin  路  3Comments

scheung38 picture scheung38  路  3Comments

tsdmrfth picture tsdmrfth  路  3Comments

updatatoday picture updatatoday  路  3Comments