如何在 FastAPI 中合理使用 Pydantic 的 Alias

下面的內容是我跟 Gemini 2.5 Pro 探討關于Pydantic 的 Alias 問題之后,讓它總結的一篇技術博客。
我已經有很長一段時間沒有好好寫技術類的博客了,這就是原因。
可以在 https://panzhixiang.cn/ 查看更多我的博客,有技術的,也有很多隨筆

作為一名后端開發者,我經常面臨的一個挑戰是如何優雅地處理外部數據表示(比如 JSON API 中的字段名)與我期望在 Python 代碼中使用的內部表示之間的差異。很多時候,前端開發者或者外部服務期望 JSON 鍵使用camelCase(駝峰命名),而我那顆 Pythonic 的心則呼喚著snake_case(蛇形命名)。又或者,我可能需要與一些遺留系統集成,它們使用的字段名可能相當晦澀,我希望能將它們映射到內部更有意義的名稱上。

這正是 Pydantic——FastAPI 的數據驗證和序列化主力軍——憑借其強大的別名功能大放異彩的地方。在這篇博客中,我想和大家分享我對aliasserialization_aliasvalidation_alias以及強大的model_config(在 Pydantic V1 中是Config類)的理解和實踐經驗,看看它們是如何幫助我馴服這些命名“叢林”的。

“為什么”:我們為什么要費心使用別名?

在我們深入“如何做”之前,讓我們先簡單聊聊“為什么”。

  1. 外部API標準:許多重度依賴 JavaScript 的前端或外部 API 強制使用camelCase(例如 userId, firstName)。
  2. 數據庫列名:數據庫的列名可能是USER_IDfirst_nm這樣的風格。
  3. 遺留系統:你可能需要集成一些字段名類似于usr_ref_id_x2的系統。
  4. Pythonic代碼:在 Python 中,snake_case(例如user_id, first_name)是約定俗成的規范(PEP 8)。遵循它能讓 Python 開發者更容易閱讀和維護代碼。

別名允許我們定義一種映射關系:“當你看到這個外部名稱時,請將它視為那個內部 Python 屬性;當你需要發送數據出去時,請為那個 Python 屬性使用另一個外部名稱。”

我們的“游樂場”:一個簡單的“書店”API

讓我們想象一下,我正在構建一個管理書籍的簡單 API。一本典型的書可能包含 ID、書名、作者和出版年份。

如果我不考慮別名,我最初的 Python 模型可能看起來是這樣的:

# 最初的想法 - 沒有別名
# from pydantic import BaseModel# class BookInternal(BaseModel):
#     book_id: str
#     title: str
#     author_name: str
#     publication_year: int

但是,前端團隊告訴我,他們期望的 JSON 負載是這樣的:

{"bookId": "some-uuid-123","bookTitle": "The Great Gatsby","authorName": "F. Scott Fitzgerald", // 這個如果忽略大小寫,看起來和 snake_case 差不多"pubYear": 1925
}

并且當他們獲取書籍信息時,也希望返回的是同樣的camelCase或者自定義的名稱。這就是我們別名探險之旅的起點。

1. alias:處理輸入數據

Field(alias="...")參數是我們的第一個工具。它告訴 Pydantic:“當你從一個字典(例如 JSON 請求體)創建這個模型的實例時,如果你看到一個名為alias_value的鍵,你應該將其值賦給這個Field所分配的 Python 屬性。”

讓我們定義一個BookCreate模型,它將用于創建新書時的輸入請求數據。

from pydantic import BaseModel, Field
from typing import Optionalclass BookCreate(BaseModel):book_id: str = Field(alias="bookId") # 將輸入的 "bookId" 映射到 Python 的 book_idtitle: str = Field(alias="bookTitle")author_name: str = Field(alias="authorName") # 外部的 "authorName" 映射到內部的 author_namepublication_year: int = Field(alias="pubYear")# 為了演示,我們再加一個可選字段isbn: Optional[str] = Field(default=None, alias="ISBN_13") # 遺留系統可能發送 ISBN_13# 示例用法 (在 FastAPI 之外,僅為理解 Pydantic):
raw_data_from_request = {"bookId": "uuid-001","bookTitle": "1984","authorName": "George Orwell","pubYear": 1949,"ISBN_13": "978-0451524935"
}book_instance = BookCreate(**raw_data_from_request)
print(f"Python book_id: {book_instance.book_id}") # 輸出: Python book_id: uuid-001
print(f"Python title: {book_instance.title}")     # 輸出: Python title: 1984
print(f"Python author_name: {book_instance.author_name}") # 輸出: Python author_name: George Orwell
print(f"Python publication_year: {book_instance.publication_year}") # 輸出: Python publication_year: 1949
print(f"Python isbn: {book_instance.isbn}") # 輸出: Python isbn: 978-0451524935

注意,在我的 Python 代碼中,我可以訪問book_instance.book_idbook_instance.publication_year,即使輸入的 JSON 使用的是bookIdpubYear。Pydantic 憑借alias妥善處理了這種轉換。

默認情況下,如果提供了別名,Pydantic 只會查找別名。如果輸入數據使用了book_id而不是bookId,它會拋出一個驗證錯誤,除非我們進行不同的配置(稍后會講到populate_by_name)。

2. serialization_alias:定制輸出數據

好了,我們現在可以接收那些名字“奇奇怪怪”的數據了。那么發送數據回去呢?如果我只是簡單地返回我的 Pydantic 模型實例,默認情況下,當它被轉換為字典(例如,用于 JSON 序列化)時,會使用 Python 的屬性名。

# 承接上文
# print(book_instance.model_dump())
# 沒有 serialization_alias 時的輸出:
# {
#     'book_id': 'uuid-001',
#     'title': '1984',
#     'author_name': 'George Orwell',
#     'publication_year': 1949,
#     'isbn': '978-0451524935'
# }

這可不是我的前端團隊想要的。他們也希望在響應中看到bookIdbookTitle等。這時候serialization_alias就派上用場了。它告訴 Pydantic:“當你將這個模型實例轉換回字典(例如,用于 JSON 響應)時,請使用這個serialization_alias_value作為該 Python 屬性的鍵。”

讓我們定義一個BookPublic模型,它將作為我們的響應模型。

class BookPublic(BaseModel):# Python 屬性名 : 類型 = Field(serialization_alias="外部名稱")book_id: str = Field(serialization_alias="bookId")title: str = Field(serialization_alias="bookTitle")author_name: str = Field(serialization_alias="authorName")publication_year: int = Field(serialization_alias="pubYear")isbn: Optional[str] = Field(default=None, serialization_alias="ISBN_13")# 讓我們用 Pythonic 的名稱創建一個實例
book_to_send = BookPublic(book_id="uuid-002",title="Brave New World",author_name="Aldous Huxley",publication_year=1932,isbn="978-0060850524"
)# print(book_to_send.model_dump(by_alias=True)) # 重要:對 model_dump 使用 by_alias=True
# 使用 serialization_alias 和 by_alias=True 時的輸出:
# {
#   "bookId": "uuid-002",
#   "bookTitle": "Brave New World",
#   "authorName": "Aldous Huxley",
#   "pubYear": 1932,
#   "ISBN_13": "978-0060850524"
# }

當使用model_dump()時,你通常需要指定by_alias=True才能讓serialization_alias生效。然而,FastAPI 非常智能!當你在response_model中使用帶有serialization_alias的模型時,FastAPI 會在底層自動處理調用model_dump(by_alias=True)(或其等效操作)。

3. 黃金搭檔:aliasserialization_alias聯手

通常情況下,輸入和輸出的外部名稱是相同的。在這種情況下,你可以在同一個字段上同時使用aliasserialization_alias

class Book(BaseModel): # 我們主要的內部表示模型book_id: str = Field(alias="bookId", serialization_alias="bookId")title: str = Field(alias="bookTitle", serialization_alias="bookTitle")# 如果 Python 內部用 author_name,外部用 authorNameauthor_name: str = Field(alias="authorName", serialization_alias="authorName")publication_year: int = Field(alias="pubYear", serialization_alias="pubYear")isbn: Optional[str] = Field(default=None, alias="ISBN_13", serialization_alias="ISBN_13")# 輸入示例
input_data = {"bookId": "uuid-003","bookTitle": "To Kill a Mockingbird","authorName": "Harper Lee","pubYear": 1960
}
book_obj = Book(**input_data)
print(f"內部訪問: {book_obj.book_id}, {book_obj.publication_year}")# 輸出示例 (FastAPI 會通過 response_model 自動完成)
output_dict = book_obj.model_dump(by_alias=True)
print(f"序列化輸出: {output_dict}")
# 輸出:
# 內部訪問: uuid-003, 1960
# 序列化輸出: {'bookId': 'uuid-003', 'bookTitle': 'To Kill a Mockingbird', 'authorName': 'Harper Lee', 'pubYear': 1960, 'ISBN_13': None}

這使我們能夠保持一致的外部命名(bookId, pubYear),同時在內部使用 Pythonic 的名稱(book_id, publication_year)。

4. validation_alias:靈活的接收器

有時,API 會演進,或者為了向后兼容,你需要為一個輸入字段支持多種命名約定。validation_alias就是你的好幫手。它允許你指定多個可能的外部名稱,這些名稱在輸入驗證/解析期間都可以映射到單個 Python 屬性。

Pydantic 會按照你定義的順序嘗試它們。如果validation_alias中的第一個別名被找到,就使用它。如果沒找到,就嘗試第二個,以此類推。如果字段本身(Python 屬性名)存在,它也可能被考慮,特別是當populate_by_name為 true 時。

假設對于book_id,我們希望接受bookId(新方式)、book_identifier(舊方式),甚至BOOK_REF(非常古老的遺留方式)。

from pydantic import RootModel # Pydantic v2, 或者 AliasPath, AliasChoicesclass BookFlexibleCreate(BaseModel):# 對于 book_id, 我們主要想接受 "bookId",# 但也兼容 "legacyBookIdentifier" 或 "oldBookRef"book_id: str = Field(validation_alias=RootModel[str](["bookId", "legacyBookIdentifier", "oldBookRef"]))# Pydantic v2 中更推薦的寫法是:# from pydantic import AliasChoices# book_id: str = Field(validation_alias=AliasChoices("bookId", "legacyBookIdentifier", "oldBookRef"))title: str = Field(alias="bookTitle") # title 仍然使用標準別名author_name: str = Field(alias="authorName")publication_year: int = Field(alias="pubYear")# validation_alias 的測試用例
data_v1 = {"bookId": "v1-id", "bookTitle": "測試書籍1", "authorName": "我", "pubYear": 2024}
data_v2 = {"legacyBookIdentifier": "v2-id", "bookTitle": "測試書籍2", "authorName": "我", "pubYear": 2024}
data_v3 = {"oldBookRef": "v3-id", "bookTitle": "測試書籍3", "authorName": "我", "pubYear": 2024}book1 = BookFlexibleCreate(**data_v1)
book2 = BookFlexibleCreate(**data_v2)
book3 = BookFlexibleCreate(**data_v3)print(f"書籍1 ID: {book1.book_id}") # 輸出: 書籍1 ID: v1-id
print(f"書籍2 ID: {book2.book_id}") # 輸出: 書籍2 ID: v2-id
print(f"書籍3 ID: {book3.book_id}") # 輸出: 書籍3 ID: v3-id# 如果同時存在多個別名呢?
# Pydantic v2: "如果存在多個別名,則會使用在選擇列表中定義的、第一個被找到的別名。"
# 這意味著如果你定義了 `validation_alias=AliasChoices("primary", "secondary")`
# 并且輸入同時包含 `{"primary": "val1", "secondary": "val2"}`,`primary` 的值將被使用。# 注意:對于序列化(輸出),validation_alias 不起作用。如果你需要特定的輸出名稱,
# 仍然需要使用 serialization_alias。如果未指定,則使用 Python 屬性名。
# 如果我總是想輸出為 "bookId":
# book_id: str = Field(
#   validation_alias=AliasChoices("bookId", "legacyBookIdentifier", "oldBookRef"),
#   serialization_alias="bookId"
# )

使用RootModel[str](["alias1", "alias2"])AliasChoices("alias1", "alias2") (對于Pydantic V2 的 AliasChoices) 是指定多個驗證別名的現代方式。在舊版本的 Pydantic 中,你可能會看到類似AliasPath的略微不同的語法。

這對于實現非破壞性的 API 變更或集成數據格式略有不同的系統非常有用。

5. model_config:全局別名行為控制

Pydantic 模型可以有一個嵌套的Config類(Pydantic V1)或一個model_config屬性(Pydantic V2,類型為ConfigDict),用于控制模型的各種行為,包括如何全局處理該模型的別名。

from pydantic import BaseModel, Field, ConfigDict # Pydantic V2
from pydantic.alias_generators import to_camel # 一個方便的工具函數# Pydantic V2 示例,使用 model_config = ConfigDict(...)
class UserProfile(BaseModel):user_id: intfull_name: stremail_address: Optional[str] = Noneis_active: bool = Field(default=True)# 配置此模型model_config = ConfigDict(populate_by_name=True, # 非常重要!alias_generator=to_camel, # 自動生成駝峰式別名# validate_assignment=True # 可選:在屬性賦值時重新驗證)# --- populate_by_name=True 的行為 ---
# 通常,如果設置了別名(即使是通過 alias_generator 設置的),Pydantic *只*會查找該別名。
# 設置 populate_by_name=True 后,Pydantic 會嘗試按 Python 字段名填充,
# *同時也*會嘗試其別名。這在你希望內部使用 Pythonic 名稱實例化模型,
# 但仍希望它能接受來自外部源的別名名稱時非常有用。# 生成的別名將是:userId, fullName, emailAddress, isActive
user_data_camel = {"userId": 1, "fullName": "Jane Doe", "emailAddress": "jane@example.com"}
user_profile_camel = UserProfile(**user_data_camel)
print(f"來自駝峰命名的數據: {user_profile_camel.user_id}, {user_profile_camel.full_name}")# 有了 populate_by_name=True,我們也可以直接使用 Python 名稱進行實例化:
user_data_snake = {"user_id": 2, "full_name": "John Smith", "is_active": False}
user_profile_snake = UserProfile(**user_data_snake)
print(f"來自蛇形命名的數據: {user_profile_snake.user_id}, {user_profile_snake.is_active}")# --- alias_generator 的行為 ---
# alias_generator 是一個函數,它接受一個字段名(str)并返回其別名(str)。
# Pydantic 提供了 to_camel 和 to_snake。你也可以編寫自己的!
# 這適用于輸入(驗證)和輸出(如果序列化時 by_alias=True)。print("來自生成器的駝峰別名:")
for name, field_info in UserProfile.model_fields.items():print(f"  字段: {name}, 別名: {field_info.alias}")# 如果使用 by_alias=True,序列化也將使用這些生成的別名
# (FastAPI 的 response_model 會這樣做)
print(f"序列化輸出 (by_alias=True): {user_profile_snake.model_dump(by_alias=True)}")
# 輸出: {'userId': 2, 'fullName': 'John Smith', 'emailAddress': None, 'isActive': False}print(f"序列化輸出 (by_alias=False 或默認): {user_profile_snake.model_dump()}")
# 輸出: {'user_id': 2, 'full_name': 'John Smith', 'email_address': None, 'is_active': False}# --- 自定義 alias_generator ---
def my_prefix_generator(field_name: str) -> str:return f"data_{field_name}"class PrefixedData(BaseModel):value_a: intvalue_b: strmodel_config = ConfigDict(alias_generator=my_prefix_generator, populate_by_name=True)# 注意:alias_generator 通常應用于 Python 字段名。
# 例如,如果 Python 字段名是 value_a,my_prefix_generator(value_a) 會生成 "data_value_a"。
# 如果我們希望先轉駝峰再加前綴,比如 to_camel(value_a) -> valueA, 然后 my_prefix_generator(valueA) -> data_valueA,
# 那么 alias_generator 需要處理這種組合,或者我們不要組合它們。
# 為了簡化,我們讓 alias_generator 直接作用于蛇形命名的 Python 字段。simple_input = {"data_value_a": 100, "data_value_b": "你好,世界"}
pd_simple_instance = PrefixedData(**simple_input) # 注意這里是 PrefixedData 而不是 PrefixedDataSimple
print(f"帶前綴的實例: {pd_simple_instance.value_a}, {pd_simple_instance.value_b}")
print(f"帶前綴的 dump 輸出: {pd_simple_instance.model_dump(by_alias=True)}")
# 輸出:
# 帶前綴的實例: 100, 你好,世界
# 帶前綴的 dump 輸出: {'data_value_a': 100, 'data_value_b': '你好,世界'}

與別名相關的關鍵model_config選項:

  • populate_by_name: bool: (Pydantic V2 中,如果存在別名,則默認為 False)。如果為 True,則允許使用 Python 字段名來初始化模型,即使該字段設置了別名。如果沒有此設置,當字段設置了別名時,Pydantic 在從字典初始化時查找別名。這在你希望為外部交互定義別名,但仍希望靈活地在內部使用 Pythonic 名稱創建模型實例時非常方便。
  • alias_generator: Callable[[str], str]: 一個函數,它接受 Python 字段名并返回一個字符串作為其別名。Pydantic 提供了pydantic.alias_generators.to_camel(轉駝峰)和to_snake(轉蛇形)。這對于在所有字段上應用一致的命名約定(例如,所有snake_case轉為camelCase)而無需為每個字段手動指定alias非常強大。這個生成的別名同時作用于驗證(輸入)和序列化(如果序列化時by_alias=True)。
  • by_alias: bool (在 model_dump 中): 這本身不是model_config的選項,但至關重要。當調用model.model_dump(by_alias=True)時,Pydantic 會優先使用serialization_alias(如果已定義),然后是alias_generator生成的任何別名,最后是alias(如果serialization_alias不存在)。如果by_alias=False(默認值),則使用 Python 屬性名。FastAPI 在處理response_model時會隱式使用by_alias=True

如果你在model_config中設置了alias_generator并且還在某個Field上顯式提供了aliasserialization_alias,那么該特定字段的顯式Field別名將具有更高的優先級。

將這一切融入 FastAPI

現在,讓我們看看這些 Pydantic 模型如何順暢地集成到 FastAPI 應用程序中。

from fastapi import FastAPI
from pydantic import BaseModel, Field, ConfigDict
from pydantic.alias_generators import to_camel
from typing import Optional, Listapp = FastAPI()# --- 我們帶有別名和配置的書籍模型 ---class BookBase(BaseModel):# 創建和公開表示所共有的字段title: strauthor_name: strpublication_year: intisbn: Optional[str] = None# 全局配置:為所有字段生成駝峰式別名# 并且也允許按 Python 名稱填充。model_config = ConfigDict(alias_generator=to_camel,populate_by_name=True)class BookCreatePayload(BookBase):# 創建時,ID 可能由外部提供,或者我們自己生成# 假設它是外部提供的,并且有一個特定的別名。# Field 上的顯式別名會覆蓋此字段的 alias_generator。book_id_external: str = Field(alias="externalBookUID")class BookDB(BookBase): # 表示它在“數據庫”(或內部服務)中可能的樣子id: str # 內部 ID,可能是一個 UUID 字符串# title, author_name 等從 BookBase 繼承,內部將使用 Python 名稱class BookPublicResponse(BookBase):# 對于公共響應,我們希望內部的 'id' 變成 'bookId'# 其他字段使用來自 alias_generator 的駝峰命名internal_id: str = Field(serialization_alias="bookId") # 將 internal_id 映射為 bookId 輸出# 確保 BookBase 中的所有字段在輸出時也使用其駝峰別名# 這由 BookBase 中的 alias_generator 和 FastAPI 對 by_alias=True 的使用來處理# 一個模擬數據庫
fake_book_db: List[BookDB] = []@app.post("/books/", response_model=BookPublicResponse, status_code=201)
async def create_book(payload: BookCreatePayload):# 'payload' 將具有 Pythonic 名稱,如 payload.title, payload.author_name# 即使請求的 JSON 使用了駝峰命名,這也要歸功于 alias_generator。# payload.book_id_external 將具有來自 "externalBookUID" 的值。print(f"收到的負載 (Python 屬性): {payload.model_dump()}")print(f"收到的 externalBookUID 為: {payload.book_id_external}")# 創建一個內部表示 (例如,用于數據庫)new_book_internal_id = f"internal-uuid-{len(fake_book_db) + 1}"book_in_db = BookDB(id=new_book_internal_id,title=payload.title, # 使用 Pythonic 名稱author_name=payload.author_name,publication_year=payload.publication_year,isbn=payload.isbn# 如果需要,我們也可以使用 payload.book_id_external)fake_book_db.append(book_in_db)# 準備響應。我們需要將 BookDB 映射到 BookPublicResponse。# BookPublicResponse 中的 'internal_id' 字段將從 book_in_db.id 填充,# 然后由于 serialization_alias,它將被序列化為 'bookId'。# 其他字段 (title, author_name) 從 BookBase 繼承,# 由于 FastAPI 的 response_model 行為,它們將使用由 alias_generator 生成的駝峰別名。response_data = BookPublicResponse(internal_id=book_in_db.id,title=book_in_db.title,author_name=book_in_db.author_name,publication_year=book_in_db.publication_year,isbn=book_in_db.isbn)return response_data@app.get("/books/{internal_id}", response_model=BookPublicResponse)
async def get_book(internal_id: str):for book in fake_book_db:if book.id == internal_id:# 構建 BookPublicResponse。# 'internal_id' 將被序列化為 'bookId'。# 其他字段將使用來自 alias_generator 的駝峰命名進行序列化。return BookPublicResponse(internal_id=book.id,title=book.title,author_name=book.author_name,publication_year=book.publication_year,isbn=book.isbn)return {"error": "未找到書籍"}, 404# 運行此應用 (保存為 main.py): uvicorn main:app --reload
#
# 使用 curl 或 Postman 向 /books/ 發送 POST 請求示例:
# URL: http://localhost:8000/books/
# 方法: POST
# Headers: Content-Type: application/json
# Body:
# {
#   "externalBookUID": "ext-999",
#   "title": "Dune",
#   "authorName": "Frank Herbert",
#   "publicationYear": 1965,
#   "isbn": "978-0441172719"
# }
#
# 預期響應 (狀態碼 201):
# {
#   "bookId": "internal-uuid-1", // 來自 internal_id,序列化為 bookId
#   "title": "Dune",             // 來自 alias_generator (如果未被 serialization_alias 覆蓋)
#   "authorName": "Frank Herbert", // 來自 alias_generator
#   "publicationYear": 1965,   // 來自 alias_generator
#   "isbn": "978-0441172719"    // 來自 alias_generator
# }

在這個 FastAPI 示例中:

  1. BookBase 使用 alias_generator=to_camelpopulate_by_name=True。這意味著:
    • 對于輸入數據,它可以接受 titleTitle(由to_camel轉換title得到,但由于populate_by_name=Truetitle本身也行)。更準確地說,它會期望title的駝峰形式 Title,但由于populate_by_name,也能接受title
    • 對于輸出數據(當 by_alias=True 時),title 會變成 Title
  2. BookCreatePayload 繼承自 BookBase。它添加了 book_id_external 字段,并指定了 alias="externalBookUID"。這個顯式別名覆蓋了該特定字段的 alias_generator。因此,對于輸入,FastAPI 期望的是 externalBookUID
  3. BookPublicResponse 也繼承自 BookBase。它添加了 internal_id 字段,并指定了 serialization_alias="bookId"。這意味著當返回 BookPublicResponse 的實例時,Python 屬性 internal_id 將在 JSON 中呈現為 bookId。其他字段如 title 將因繼承的 alias_generator 而呈現為 Title(駝峰式)。
  4. FastAPI 在序列化 response_model 時會自動處理 by_alias=True
  5. create_book 端點內部,payload: BookCreatePayload 意味著 FastAPI 會解析傳入的 JSON。它使用別名(externalBookUID,以及來自 alias_generator 的駝峰別名)來填充 payload 對象。然后我們可以使用 Python 名稱訪問屬性(例如 payload.title, payload.book_id_external)。
  6. 當返回 response_dataBookPublicResponse 的實例)時,FastAPI 會使用其 serialization_aliasinternal_id -> bookId)以及其他字段的 alias_generator

常見陷阱與最佳實踐

  • 忘記 response_modelby_alias=True:如果你手動將 Pydantic 模型轉換為字典作為響應,并且忘記了 model_dump(by_alias=True),那么你的 serialization_aliasalias_generator(用于輸出)將不會生效。FastAPI 的 response_model 會為你處理好這一點。
  • alias vs. serialization_alias vs. validation_alias 的辨析
    • alias: 主要用于輸入,但如果未設置 serialization_aliasby_alias=True,它也作為輸出的后備。
    • serialization_alias: 僅用于輸出 (model_dump(by_alias=True))。
    • validation_alias: 僅用于輸入,允許指定多個備選別名。
  • populate_by_name:理解它的影響。如果為 False(當存在別名時的默認值),你的模型只能通過別名來填充。如果為 True,則可以通過 Python 名稱別名來填充,這通常更靈活。
  • 優先級:顯式的 Field 別名(alias, serialization_alias)會覆蓋 alias_generator。對于具有多個選項的 validation_alias,定義的順序很重要。
  • 清晰性 vs. “魔法”:雖然 alias_generator 很強大,但要注意它增加了一層“魔法”。如果有人閱讀你的 Pydantic 模型定義,除非他們也檢查 model_config,否則可能不會立即看到外部字段名。對于非常復雜或非標準的映射,顯式的 Field(alias=...) 有時可能更清晰。
  • 測試:始終使用實際的 JSON 負載測試你的 API,以確保別名在請求和響應中都按預期工作。

總結

Pydantic 的別名系統是一個非常靈活和強大的特性。通過理解aliasserialization_aliasvalidation_alias,以及如何使用model_config(特別是populate_by_namealias_generator)進行全局配置,我已經能夠編寫出更簡潔、更 Pythonic 的后端代碼,同時無縫地與各種外部命名約定集成。掌握哪個別名做什么可能需要一點練習,但一旦你掌握了,它就像是使用 FastAPI 進行 API 開發的一項超能力!

我希望這次的深入探討能幫助你應對你自己的命名約定挑戰。編碼愉快!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/81992.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/81992.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/81992.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

CAU人工智能class4 批次歸一化

歸一化 在對輸入數據進行預處理時會用到歸一化,將輸入數據的范圍收縮到0到1之間,這有利于避免綱量對模型訓練產生的影響。 但當模型過深時會產生下述問題: 當一個學習系統的輸入分布發生變化時,這種現象稱之為“內部協變量偏移”…

動態庫和靜態庫詳解

庫其實就是個文件 下面是文件后綴 靜態庫:.a(linux) .lib(windows) 動態庫:.so(linux) .dll(windows) 靜態庫的制作 ar -rc libmystdio.a my_stdio.o my_string.o ar是歸檔工具,rc表示replace和create,ar跟tar有點…

PDF 文檔結構化工具對比:Marker 與 MinerU

模型訓練數據-MinerU一款Pdf轉Markdown軟件 https://codeyuan.blog.csdn.net/article/details/144315141 在當前大模型(LLM)和自然語言處理(NLP)應用快速發展的背景下,如何高效地將 PDF 等非結構化文檔轉換為結構化數…

shp2pgsql 導入 Shp 到 PostGIS 空間數據庫

前言 ? shp2pgsql是PostGIS自帶的命令行工具,用于將Shapefile文件聲稱SQL腳本導入到PostGIS空間數據庫。 1. 安裝 PostGIS 通過Application Stack Builder或者下載單獨的PostGIS包進行安裝。而shp2pgsql則是與PostGIS工具集成在一起,無需單獨下載。該命…

【ISP算法精粹】什么是global tone mapping和local tone mapping?

1. 簡介 全局色調映射(Global Tone Mapping)和局部色調映射(Local Tone Mapping)是高動態范圍(HDR)圖像處理中的兩種關鍵技術,用于將高動態范圍圖像的亮度值映射到標準動態范圍(LDR…

虛擬環境中VSCode運行jupyter文件

用VS Code打開jupyter文件,點擊右上角 Select Kernel 在正上方會出現這個選擇框,選擇 Python Environment 會出來所有的虛擬環境,選擇要用的環境行

如何計算VLLM本地部署Qwen3-4B的GPU最小配置應該是多少?多人并發訪問本地大模型的GPU配置應該怎么分配?

本文一定要閱讀我上篇文章!!! 超詳細VLLM框架部署qwen3-4B加混合推理探索!!!-CSDN博客 本文是基于上篇文章遺留下的問題進行說明的。 一、本文解決的問題 問題1:我明明只部署了qwen3-4B的模型…

antv/g6 圖譜封裝配置(二)

繼上次實現圖譜后,后續發現如果要繼續加入不同樣式的圖譜實現起來太過麻煩,因此考慮將配置項全部提取封裝到js文件中,圖譜組件只專注于實現各種不同的組件,其中主要封裝的點就是各個節點的橫坐標(x),縱坐標…

從芯片互連到機器人革命:英偉達雙線出擊,NVLink開放生態+GR00T模型定義AI計算新時代

5月19日,在臺灣舉辦的Computex 2025上,英偉達推出新技術“NVLink Fusion”,允許非英偉達CPU和GPU,同英偉達產品以及高速GPU互連技術NVLink結合使用,加速AI芯片連接。新技術的推出旨在保持英偉達在人工智能開發和計算領…

Qt window frame + windowTitle + windowIcon屬性(3)

文章目錄 window frame屬性window frame的概念1. window frame的影響2. 圖片演示3. 代碼演示 API接口widget.cpp(測試代碼) windowTitle屬性API接口問題 注意點widget.cpp(屬性用法) windowIcon屬性API接口啥是窗口圖標玩法1. 先…

Git 分支管理:merge、rebase、cherry-pick 的用法與規范

Git 分支管理:merge、rebase、cherry-pick 的用法與規范 在團隊開發和個人項目中,合理管理 Git 分支至關重要。merge、rebase 和 cherry-pick 是最常用的三種分支操作命令。本文將介紹它們的基本用法、適用場景及最佳實踐規范,幫助大家更高效…

VR全景制作方法都有哪些?需要注意什么?

VR全景制作是將線下實景場景轉化為具有沉浸式體驗的全景圖像的相關技術流程。通過圖像處理和軟件拼接等手段及技術,可以制作出VR全景圖。后面,我們科普詳細的VR全景制作方法指南,順便介紹眾趣科技在相關領域提供的支持方案。 選定拍攝地點與準…

計算機系統結構1-3章節 期末背誦內容

Amdahl定律: 加快某部件執行速度所能獲得的系統性能加速比,受限于該部件的執行時間占系統中總執行時間的百分比。 加速比依賴于: 可改進比例:在改進前的系統中,可改進部分的執行時間在總的執行時間中所占的比例。 部件加速比:可改…

JS實現直接下載PDF文件

pdf文件通過a標簽直接下載會打開頁面,所以,請求該文件的blob文件流數據,再通過window.URL.createObjectURL轉成鏈接,就可以直接下載了。 只需要替換url和文件名稱就行,文件名的后綴記得要寫上pdf,不然會變成…

深度解析Pytest中Fixture機制與實戰案例

一、為什么我們需要Fixture? 在某次金融系統重構項目中,我們的測試團隊曾遇到這樣的困境:隨著測試用例增長到500,使用unittest框架編寫的測試代碼出現了嚴重的維護問題——setup方法臃腫不堪,測試數據混亂&#xff0c…

文檔結構化專家:數字化轉型的核心力量

文檔結構化專家:定義、職責與行業應用的全方位解析 一、文檔結構化的定義與核心價值 文檔結構化是將非結構化或半結構化文檔(如文本、圖像、表格)轉換為計算機可處理的規范化數據形式的過程。其核心在于通過語義解析、信息單元劃分和標準化格式(如XML/JSON),實現信息的…

Linux系統管理與編程16番外篇:PXE自動化安裝部署OpenEuler24.03LTS

蘭生幽谷,不為莫服而不芳; 君子行義,不為莫知而止休。 Preboot Execution Environment 本機服務器操作系統:CentOS7.9.2207 目標服務器安裝系統:openEuler-24.03-LTS-SP1-everything-x86_64-dvd.iso 虛擬機&#xff1…

Enhanced RTMP H.265(HEVC)技術規格解析:流媒體協議的新突破

Enhanced RTMP H.265(HEVC)技術規格解析:流媒體協議的新突破 “每一幀畫面都是時間的映射,壓縮之后的靈魂,依然能栩栩如生。” 隨著流媒體技術的快速發展,視頻編碼標準不斷推陳出新。H.264/AVC雖然已經成為…

Visual Studio Code 改成中文模式(漢化)

1、打開工具軟件(雙擊打開) 2、軟件左邊圖標點開 3、在搜索框,搜索 chinese 出現的第一個 就是簡體中文 4、點擊第一個簡體中文,右邊會出來基本信息 點擊 install 就可以安裝了(記得聯網)。 5、安裝完右…

Linux--初識文件系統fd

01. C/系統調用文件操作 C/系統調用文件操作 02. 文件系統(ext2)結構 Linux ext2文件系統,上圖為磁盤文件系統圖(內核內存映像肯定有所不同),磁盤是典型的塊設備,硬盤分區被劃分為一個個的block。一個塊的大小(有1MB,…