Change Pydantic's inherited BaseModel's attribute precedence in JSON schema

Viewed 1547

I'm using pydantic 1.6.1 and fastapi 0.61.1 with Python 3.8.3. Here's how I've tried defining the models:

class UserBase(BaseModel):
    name: str

class UserCreate(UserBase):
    password: str

class UserInfo(UserBase):
    id: str
    group: Optional[GroupInfo] = None

The issue I'm having with this setup is that the schema is built such that the name attribute is on top of the remaining attributes like so - in this case, while using UserInfo as the endpoint's response_model:

[
  {
    "name": "string",
    "id": "string",
    "group": {
      "name": "string"
    }
  }
]

Yet I'd like to be able to set them up like this:

[
  {
    "id": "string",
    "name": "string",
    "group": {
      "name": "string"
    }
  }
]

Is there a way I can manually set a custom order for the attributes in the JSON response's schema?

1 Answers

As I mentioned in my comment, it doesn't really matter the order of the JSON, but when it comes to schema generation, it can be helpful.

You need to decouple the id field from UserInfo model as

class UserID(BaseModel):
    id: str


class UserInfo(UserBase, UserID): # `UserID` should be second
    group: Optional[GroupInfo] = None

This will generate the following JSON schema,

{
  "id": "string",
  "name": "string",
  "group": {
    "name": "string"
  }
}

Bit more ugly solution (IMO)

patch the .__fields__ as

class UserBase(BaseModel):
    name: str


class UserCreate(UserBase):
    password: str


class UserInfo(UserBase):
    id: str
    group: Optional[GroupInfo] = None


fields = UserInfo.__fields__.copy()
UserInfo.__fields__ = {"id": fields.pop("id"), **fields}
Related