[{"data":1,"prerenderedAt":1751},["ShallowReactive",2],{"page-\u002Fadvanced-pydantic-validation-serialization\u002Fpydantic-v2-migration-guide\u002F":3,"nav":1605,"surround-\u002Fadvanced-pydantic-validation-serialization\u002Fpydantic-v2-migration-guide\u002F":1749},{"id":4,"title":5,"body":6,"description":1598,"extension":1599,"meta":1600,"navigation":118,"path":1601,"seo":1602,"stem":1603,"__hash__":1604},"content\u002Fadvanced-pydantic-validation-serialization\u002Fpydantic-v2-migration-guide\u002Findex.md","Pydantic V2 Migration Guide: FastAPI Production Patterns",{"type":7,"value":8,"toc":1582},"minimark",[9,13,23,28,44,49,64,307,313,333,337,370,374,381,746,751,804,808,829,833,1097,1102,1127,1131,1150,1154,1161,1329,1334,1369,1373,1492,1496,1501,1518,1526,1545,1550,1566,1571,1578],[10,11,5],"h1",{"id":12},"pydantic-v2-migration-guide-fastapi-production-patterns",[14,15,16,17,22],"p",{},"Upgrading to Pydantic V2 is not a drop-in replacement; it is an architectural pivot that trades legacy Python-based introspection for a compiled Rust validation core. For backend engineers, this transition delivers measurable latency reductions but introduces strict typing defaults, altered serialization semantics, and a restructured configuration API. A successful migration requires phased dependency updates, explicit schema alignment, and rigorous observability around validation boundaries. Understanding the foundational shifts in ",[18,19,21],"a",{"href":20},"\u002Fadvanced-pydantic-validation-serialization\u002F","Advanced Pydantic Validation & Serialization"," is critical before initiating production rollouts, as uncoordinated upgrades frequently trigger silent data coercion failures or OpenAPI contract drift.",[24,25,27],"h2",{"id":26},"core-engine-configuration-shifts","Core Engine & Configuration Shifts",[14,29,30,31,35,36,39,40,43],{},"Pydantic V2 delegates validation and serialization to ",[32,33,34],"code",{},"pydantic-core",", a Rust extension that bypasses Python's dynamic type resolution overhead. The immediate operational impact is a 5–10x throughput increase for high-volume request parsing, but it enforces stricter type boundaries by default. Legacy ",[32,37,38],{},"class Config"," inner classes are deprecated in favor of ",[32,41,42],{},"model_config = ConfigDict(...)",", which improves static analysis compatibility and reduces runtime metaclass instantiation costs.",[45,46,48],"h3",{"id":47},"production-configuration-migration","Production Configuration Migration",[14,50,51,52,55,56,59,60,63],{},"The ",[32,53,54],{},"ConfigDict"," paradigm centralizes model behavior. Note that ",[32,57,58],{},"validate_assignment"," and ",[32,61,62],{},"str_strip_whitespace"," remain supported but now operate under stricter coercion rules.",[65,66,71],"pre",{"className":67,"code":68,"language":69,"meta":70,"style":70},"language-python shiki shiki-themes github-light","from pydantic import BaseModel, ConfigDict, field_validator\nfrom typing import Optional\nimport logging\n\nlogger = logging.getLogger(__name__)\n\nclass UserCreate(BaseModel):\n # V2 Configuration: Explicit, IDE-friendly, and compiled at model definition time\n model_config = ConfigDict(\n str_strip_whitespace=True,\n validate_assignment=True,\n extra=\"forbid\", # Enforces strict schema compliance in production\n json_schema_extra={\"examples\": [{\"email\": \"user@example.com\"}]}\n )\n\n email: str\n username: Optional[str] = None\n age: Optional[int] = None\n","python","",[32,72,73,92,105,113,120,139,144,163,170,181,196,208,226,255,261,266,275,292],{"__ignoreMap":70},[74,75,78,82,86,89],"span",{"class":76,"line":77},"line",1,[74,79,81],{"class":80},"sD7c4","from",[74,83,85],{"class":84},"sgsFI"," pydantic ",[74,87,88],{"class":80},"import",[74,90,91],{"class":84}," BaseModel, ConfigDict, field_validator\n",[74,93,95,97,100,102],{"class":76,"line":94},2,[74,96,81],{"class":80},[74,98,99],{"class":84}," typing ",[74,101,88],{"class":80},[74,103,104],{"class":84}," Optional\n",[74,106,108,110],{"class":76,"line":107},3,[74,109,88],{"class":80},[74,111,112],{"class":84}," logging\n",[74,114,116],{"class":76,"line":115},4,[74,117,119],{"emptyLinePlaceholder":118},true,"\n",[74,121,123,126,129,132,136],{"class":76,"line":122},5,[74,124,125],{"class":84},"logger ",[74,127,128],{"class":80},"=",[74,130,131],{"class":84}," logging.getLogger(",[74,133,135],{"class":134},"sYu0t","__name__",[74,137,138],{"class":84},")\n",[74,140,142],{"class":76,"line":141},6,[74,143,119],{"emptyLinePlaceholder":118},[74,145,147,150,154,157,160],{"class":76,"line":146},7,[74,148,149],{"class":80},"class",[74,151,153],{"class":152},"s7eDp"," UserCreate",[74,155,156],{"class":84},"(",[74,158,159],{"class":152},"BaseModel",[74,161,162],{"class":84},"):\n",[74,164,166],{"class":76,"line":165},8,[74,167,169],{"class":168},"sAwPA"," # V2 Configuration: Explicit, IDE-friendly, and compiled at model definition time\n",[74,171,173,176,178],{"class":76,"line":172},9,[74,174,175],{"class":84}," model_config ",[74,177,128],{"class":80},[74,179,180],{"class":84}," ConfigDict(\n",[74,182,184,188,190,193],{"class":76,"line":183},10,[74,185,187],{"class":186},"sqxcx"," str_strip_whitespace",[74,189,128],{"class":80},[74,191,192],{"class":134},"True",[74,194,195],{"class":84},",\n",[74,197,199,202,204,206],{"class":76,"line":198},11,[74,200,201],{"class":186}," validate_assignment",[74,203,128],{"class":80},[74,205,192],{"class":134},[74,207,195],{"class":84},[74,209,211,214,216,220,223],{"class":76,"line":210},12,[74,212,213],{"class":186}," extra",[74,215,128],{"class":80},[74,217,219],{"class":218},"sYBdl","\"forbid\"",[74,221,222],{"class":84},", ",[74,224,225],{"class":168},"# Enforces strict schema compliance in production\n",[74,227,229,232,234,237,240,243,246,249,252],{"class":76,"line":228},13,[74,230,231],{"class":186}," json_schema_extra",[74,233,128],{"class":80},[74,235,236],{"class":84},"{",[74,238,239],{"class":218},"\"examples\"",[74,241,242],{"class":84},": [{",[74,244,245],{"class":218},"\"email\"",[74,247,248],{"class":84},": ",[74,250,251],{"class":218},"\"user@example.com\"",[74,253,254],{"class":84},"}]}\n",[74,256,258],{"class":76,"line":257},14,[74,259,260],{"class":84}," )\n",[74,262,264],{"class":76,"line":263},15,[74,265,119],{"emptyLinePlaceholder":118},[74,267,269,272],{"class":76,"line":268},16,[74,270,271],{"class":84}," email: ",[74,273,274],{"class":134},"str\n",[74,276,278,281,284,287,289],{"class":76,"line":277},17,[74,279,280],{"class":84}," username: Optional[",[74,282,283],{"class":134},"str",[74,285,286],{"class":84},"] ",[74,288,128],{"class":80},[74,290,291],{"class":134}," None\n",[74,293,295,298,301,303,305],{"class":76,"line":294},18,[74,296,297],{"class":84}," age: Optional[",[74,299,300],{"class":134},"int",[74,302,286],{"class":84},[74,304,128],{"class":80},[74,306,291],{"class":134},[14,308,309],{},[310,311,312],"strong",{},"Trade-offs & Observability:",[314,315,316,323,330],"ul",{},[317,318,319,322],"li",{},[32,320,321],{},"extra=\"forbid\""," is highly recommended for V2 to prevent silent payload bloat.",[317,324,325,326,329],{},"Enable structured logging for ",[32,327,328],{},"ValidationError"," traces to monitor strict-mode rejections in production.",[317,331,332],{},"The Rust core caches compiled validators per model class; avoid dynamic model generation in hot paths to prevent memory fragmentation.",[24,334,336],{"id":335},"validator-syntax-overhaul-custom-logic","Validator Syntax Overhaul & Custom Logic",[14,338,339,340,59,343,346,347,59,350,353,354,357,358,361,362,365,366,369],{},"The decorator-based validation system has been completely refactored. Legacy ",[32,341,342],{},"@validator",[32,344,345],{},"@root_validator"," are replaced by ",[32,348,349],{},"@field_validator",[32,351,352],{},"@model_validator",", which now require explicit ",[32,355,356],{},"mode"," parameters and ",[32,359,360],{},"@classmethod"," decoration. Crucially, V2 validators execute ",[310,363,364],{},"after"," type coercion by default (",[32,367,368],{},"mode='after'","), whereas V1 executed before. Misaligning this assumption is a primary source of production validation bypasses.",[45,371,373],{"id":372},"production-validator-implementation","Production Validator Implementation",[14,375,376,377,380],{},"Validators must now explicitly handle type hints and raise standard exceptions or ",[32,378,379],{},"pydantic.ValidationError"," for graceful FastAPI integration.",[65,382,384],{"className":67,"code":383,"language":69,"meta":70,"style":70},"from pydantic import BaseModel, field_validator, ValidationInfo, ValidationError\nfrom datetime import datetime\nimport re\n\nclass OrderPayload(BaseModel):\n sku: str\n quantity: int\n requested_at: datetime\n\n # V2 Pattern: Explicit mode, classmethod, and ValidationInfo for context\n @field_validator(\"sku\", mode=\"before\")\n @classmethod\n def normalize_sku(cls, v: str, info: ValidationInfo) -> str:\n if not isinstance(v, str):\n raise ValueError(\"SKU must be a string before normalization\")\n normalized = v.strip().upper()\n if not re.match(r\"^[A-Z]{3}-\\d{4}$\", normalized):\n raise ValueError(f\"Invalid SKU format: {v}\")\n return normalized\n\n @field_validator(\"quantity\", mode=\"after\")\n @classmethod\n def enforce_quantity_limits(cls, v: int, info: ValidationInfo) -> int:\n if v \u003C= 0:\n raise ValueError(\"Quantity must be positive\")\n if v > 10000:\n raise ValueError(\"Quantity exceeds warehouse threshold\")\n return v\n",[32,385,386,397,409,416,420,433,440,448,453,457,462,483,491,512,530,545,555,593,619,628,633,654,661,679,695,709,724,738],{"__ignoreMap":70},[74,387,388,390,392,394],{"class":76,"line":77},[74,389,81],{"class":80},[74,391,85],{"class":84},[74,393,88],{"class":80},[74,395,396],{"class":84}," BaseModel, field_validator, ValidationInfo, ValidationError\n",[74,398,399,401,404,406],{"class":76,"line":94},[74,400,81],{"class":80},[74,402,403],{"class":84}," datetime ",[74,405,88],{"class":80},[74,407,408],{"class":84}," datetime\n",[74,410,411,413],{"class":76,"line":107},[74,412,88],{"class":80},[74,414,415],{"class":84}," re\n",[74,417,418],{"class":76,"line":115},[74,419,119],{"emptyLinePlaceholder":118},[74,421,422,424,427,429,431],{"class":76,"line":122},[74,423,149],{"class":80},[74,425,426],{"class":152}," OrderPayload",[74,428,156],{"class":84},[74,430,159],{"class":152},[74,432,162],{"class":84},[74,434,435,438],{"class":76,"line":141},[74,436,437],{"class":84}," sku: ",[74,439,274],{"class":134},[74,441,442,445],{"class":76,"line":146},[74,443,444],{"class":84}," quantity: ",[74,446,447],{"class":134},"int\n",[74,449,450],{"class":76,"line":165},[74,451,452],{"class":84}," requested_at: datetime\n",[74,454,455],{"class":76,"line":172},[74,456,119],{"emptyLinePlaceholder":118},[74,458,459],{"class":76,"line":183},[74,460,461],{"class":168}," # V2 Pattern: Explicit mode, classmethod, and ValidationInfo for context\n",[74,463,464,467,469,472,474,476,478,481],{"class":76,"line":198},[74,465,466],{"class":152}," @field_validator",[74,468,156],{"class":84},[74,470,471],{"class":218},"\"sku\"",[74,473,222],{"class":84},[74,475,356],{"class":186},[74,477,128],{"class":80},[74,479,480],{"class":218},"\"before\"",[74,482,138],{"class":84},[74,484,485,488],{"class":76,"line":210},[74,486,487],{"class":152}," @",[74,489,490],{"class":134},"classmethod\n",[74,492,493,496,499,502,504,507,509],{"class":76,"line":228},[74,494,495],{"class":80}," def",[74,497,498],{"class":152}," normalize_sku",[74,500,501],{"class":84},"(cls, v: ",[74,503,283],{"class":134},[74,505,506],{"class":84},", info: ValidationInfo) -> ",[74,508,283],{"class":134},[74,510,511],{"class":84},":\n",[74,513,514,517,520,523,526,528],{"class":76,"line":257},[74,515,516],{"class":80}," if",[74,518,519],{"class":80}," not",[74,521,522],{"class":134}," isinstance",[74,524,525],{"class":84},"(v, ",[74,527,283],{"class":134},[74,529,162],{"class":84},[74,531,532,535,538,540,543],{"class":76,"line":263},[74,533,534],{"class":80}," raise",[74,536,537],{"class":134}," ValueError",[74,539,156],{"class":84},[74,541,542],{"class":218},"\"SKU must be a string before normalization\"",[74,544,138],{"class":84},[74,546,547,550,552],{"class":76,"line":268},[74,548,549],{"class":84}," normalized ",[74,551,128],{"class":80},[74,553,554],{"class":84}," v.strip().upper()\n",[74,556,557,559,561,564,567,570,573,576,579,582,585,588,590],{"class":76,"line":277},[74,558,516],{"class":80},[74,560,519],{"class":80},[74,562,563],{"class":84}," re.match(",[74,565,566],{"class":80},"r",[74,568,569],{"class":218},"\"",[74,571,572],{"class":134},"^[A-Z]",[74,574,575],{"class":80},"{3}",[74,577,578],{"class":218},"-",[74,580,581],{"class":134},"\\d",[74,583,584],{"class":80},"{4}",[74,586,587],{"class":134},"$",[74,589,569],{"class":218},[74,591,592],{"class":84},", normalized):\n",[74,594,595,597,599,601,604,607,609,612,615,617],{"class":76,"line":294},[74,596,534],{"class":80},[74,598,537],{"class":134},[74,600,156],{"class":84},[74,602,603],{"class":80},"f",[74,605,606],{"class":218},"\"Invalid SKU format: ",[74,608,236],{"class":134},[74,610,611],{"class":84},"v",[74,613,614],{"class":134},"}",[74,616,569],{"class":218},[74,618,138],{"class":84},[74,620,622,625],{"class":76,"line":621},19,[74,623,624],{"class":80}," return",[74,626,627],{"class":84}," normalized\n",[74,629,631],{"class":76,"line":630},20,[74,632,119],{"emptyLinePlaceholder":118},[74,634,636,638,640,643,645,647,649,652],{"class":76,"line":635},21,[74,637,466],{"class":152},[74,639,156],{"class":84},[74,641,642],{"class":218},"\"quantity\"",[74,644,222],{"class":84},[74,646,356],{"class":186},[74,648,128],{"class":80},[74,650,651],{"class":218},"\"after\"",[74,653,138],{"class":84},[74,655,657,659],{"class":76,"line":656},22,[74,658,487],{"class":152},[74,660,490],{"class":134},[74,662,664,666,669,671,673,675,677],{"class":76,"line":663},23,[74,665,495],{"class":80},[74,667,668],{"class":152}," enforce_quantity_limits",[74,670,501],{"class":84},[74,672,300],{"class":134},[74,674,506],{"class":84},[74,676,300],{"class":134},[74,678,511],{"class":84},[74,680,682,684,687,690,693],{"class":76,"line":681},24,[74,683,516],{"class":80},[74,685,686],{"class":84}," v ",[74,688,689],{"class":80},"\u003C=",[74,691,692],{"class":134}," 0",[74,694,511],{"class":84},[74,696,698,700,702,704,707],{"class":76,"line":697},25,[74,699,534],{"class":80},[74,701,537],{"class":134},[74,703,156],{"class":84},[74,705,706],{"class":218},"\"Quantity must be positive\"",[74,708,138],{"class":84},[74,710,712,714,716,719,722],{"class":76,"line":711},26,[74,713,516],{"class":80},[74,715,686],{"class":84},[74,717,718],{"class":80},">",[74,720,721],{"class":134}," 10000",[74,723,511],{"class":84},[74,725,727,729,731,733,736],{"class":76,"line":726},27,[74,728,534],{"class":80},[74,730,537],{"class":134},[74,732,156],{"class":84},[74,734,735],{"class":218},"\"Quantity exceeds warehouse threshold\"",[74,737,138],{"class":84},[74,739,741,743],{"class":76,"line":740},28,[74,742,624],{"class":80},[74,744,745],{"class":84}," v\n",[14,747,748],{},[310,749,750],{},"Implementation Notes:",[314,752,753,766,772],{},[317,754,755,758,759,761,762,765],{},[32,756,757],{},"mode=\"before\""," receives raw input (often ",[32,760,283],{}," or ",[32,763,764],{},"dict","). Use it for normalization or format checks.",[317,767,768,771],{},[32,769,770],{},"mode=\"after\""," receives the coerced Python type. Use it for business logic constraints.",[317,773,51,774,777,778,59,781,784,785,222,788,791,792,795,796,800,801,803],{},[32,775,776],{},"ValidationInfo"," object replaces legacy ",[32,779,780],{},"values",[32,782,783],{},"field"," arguments, providing ",[32,786,787],{},"data",[32,789,790],{},"config",", and ",[32,793,794],{},"context"," for cross-field validation. For deeper constraint patterns, consult ",[18,797,799],{"href":798},"\u002Fadvanced-pydantic-validation-serialization\u002Fcustom-validators-field-constraints\u002F","Custom Validators & Field Constraints"," to map legacy ",[32,802,342],{}," logic to V2's type-safe execution pipeline.",[24,805,807],{"id":806},"serialization-pipeline-nested-structures","Serialization Pipeline & Nested Structures",[14,809,810,811,59,814,817,818,59,821,824,825,828],{},"V2 deprecates ",[32,812,813],{},".dict()",[32,815,816],{},".json()"," entirely. The new ",[32,819,820],{},".model_dump()",[32,822,823],{},".model_dump_json()"," methods leverage the compiled Rust serializer, offering significant CPU savings but altering default behavior around ",[32,826,827],{},"None"," and unset fields.",[45,830,832],{"id":831},"serialization-strategy","Serialization Strategy",[65,834,836],{"className":67,"code":835,"language":69,"meta":70,"style":70},"from pydantic import BaseModel\nfrom typing import List, Optional\n\nclass Address(BaseModel):\n line1: str\n city: str\n postal_code: Optional[str] = None\n\nclass Customer(BaseModel):\n name: str\n addresses: List[Address] = []\n\n# Production Serialization Patterns\ncustomer = Customer(name=\"Acme Corp\", addresses=[Address(line1=\"123 Main St\", city=\"NYC\")])\n\n# 1. exclude_unset: Omits fields that were never explicitly set during instantiation\n# Ideal for PATCH endpoints to avoid overwriting DB defaults with None\npartial_payload = customer.model_dump(exclude_unset=True)\n\n# 2. exclude_none: Omits fields explicitly set to None\n# Ideal for external API contracts that reject null values\nclean_payload = customer.model_dump(exclude_none=True)\n\n# 3. JSON serialization with explicit encoding\njson_bytes = customer.model_dump_json(by_alias=True, exclude_unset=True)\n",[32,837,838,849,860,864,877,884,891,904,908,921,928,938,942,947,996,1000,1005,1010,1029,1033,1038,1043,1061,1065,1070],{"__ignoreMap":70},[74,839,840,842,844,846],{"class":76,"line":77},[74,841,81],{"class":80},[74,843,85],{"class":84},[74,845,88],{"class":80},[74,847,848],{"class":84}," BaseModel\n",[74,850,851,853,855,857],{"class":76,"line":94},[74,852,81],{"class":80},[74,854,99],{"class":84},[74,856,88],{"class":80},[74,858,859],{"class":84}," List, Optional\n",[74,861,862],{"class":76,"line":107},[74,863,119],{"emptyLinePlaceholder":118},[74,865,866,868,871,873,875],{"class":76,"line":115},[74,867,149],{"class":80},[74,869,870],{"class":152}," Address",[74,872,156],{"class":84},[74,874,159],{"class":152},[74,876,162],{"class":84},[74,878,879,882],{"class":76,"line":122},[74,880,881],{"class":84}," line1: ",[74,883,274],{"class":134},[74,885,886,889],{"class":76,"line":141},[74,887,888],{"class":84}," city: ",[74,890,274],{"class":134},[74,892,893,896,898,900,902],{"class":76,"line":146},[74,894,895],{"class":84}," postal_code: Optional[",[74,897,283],{"class":134},[74,899,286],{"class":84},[74,901,128],{"class":80},[74,903,291],{"class":134},[74,905,906],{"class":76,"line":165},[74,907,119],{"emptyLinePlaceholder":118},[74,909,910,912,915,917,919],{"class":76,"line":172},[74,911,149],{"class":80},[74,913,914],{"class":152}," Customer",[74,916,156],{"class":84},[74,918,159],{"class":152},[74,920,162],{"class":84},[74,922,923,926],{"class":76,"line":183},[74,924,925],{"class":84}," name: ",[74,927,274],{"class":134},[74,929,930,933,935],{"class":76,"line":198},[74,931,932],{"class":84}," addresses: List[Address] ",[74,934,128],{"class":80},[74,936,937],{"class":84}," []\n",[74,939,940],{"class":76,"line":210},[74,941,119],{"emptyLinePlaceholder":118},[74,943,944],{"class":76,"line":228},[74,945,946],{"class":168},"# Production Serialization Patterns\n",[74,948,949,952,954,957,960,962,965,967,970,972,975,978,980,983,985,988,990,993],{"class":76,"line":257},[74,950,951],{"class":84},"customer ",[74,953,128],{"class":80},[74,955,956],{"class":84}," Customer(",[74,958,959],{"class":186},"name",[74,961,128],{"class":80},[74,963,964],{"class":218},"\"Acme Corp\"",[74,966,222],{"class":84},[74,968,969],{"class":186},"addresses",[74,971,128],{"class":80},[74,973,974],{"class":84},"[Address(",[74,976,977],{"class":186},"line1",[74,979,128],{"class":80},[74,981,982],{"class":218},"\"123 Main St\"",[74,984,222],{"class":84},[74,986,987],{"class":186},"city",[74,989,128],{"class":80},[74,991,992],{"class":218},"\"NYC\"",[74,994,995],{"class":84},")])\n",[74,997,998],{"class":76,"line":263},[74,999,119],{"emptyLinePlaceholder":118},[74,1001,1002],{"class":76,"line":268},[74,1003,1004],{"class":168},"# 1. exclude_unset: Omits fields that were never explicitly set during instantiation\n",[74,1006,1007],{"class":76,"line":277},[74,1008,1009],{"class":168},"# Ideal for PATCH endpoints to avoid overwriting DB defaults with None\n",[74,1011,1012,1015,1017,1020,1023,1025,1027],{"class":76,"line":294},[74,1013,1014],{"class":84},"partial_payload ",[74,1016,128],{"class":80},[74,1018,1019],{"class":84}," customer.model_dump(",[74,1021,1022],{"class":186},"exclude_unset",[74,1024,128],{"class":80},[74,1026,192],{"class":134},[74,1028,138],{"class":84},[74,1030,1031],{"class":76,"line":621},[74,1032,119],{"emptyLinePlaceholder":118},[74,1034,1035],{"class":76,"line":630},[74,1036,1037],{"class":168},"# 2. exclude_none: Omits fields explicitly set to None\n",[74,1039,1040],{"class":76,"line":635},[74,1041,1042],{"class":168},"# Ideal for external API contracts that reject null values\n",[74,1044,1045,1048,1050,1052,1055,1057,1059],{"class":76,"line":656},[74,1046,1047],{"class":84},"clean_payload ",[74,1049,128],{"class":80},[74,1051,1019],{"class":84},[74,1053,1054],{"class":186},"exclude_none",[74,1056,128],{"class":80},[74,1058,192],{"class":134},[74,1060,138],{"class":84},[74,1062,1063],{"class":76,"line":663},[74,1064,119],{"emptyLinePlaceholder":118},[74,1066,1067],{"class":76,"line":681},[74,1068,1069],{"class":168},"# 3. JSON serialization with explicit encoding\n",[74,1071,1072,1075,1077,1080,1083,1085,1087,1089,1091,1093,1095],{"class":76,"line":697},[74,1073,1074],{"class":84},"json_bytes ",[74,1076,128],{"class":80},[74,1078,1079],{"class":84}," customer.model_dump_json(",[74,1081,1082],{"class":186},"by_alias",[74,1084,128],{"class":80},[74,1086,192],{"class":134},[74,1088,222],{"class":84},[74,1090,1022],{"class":186},[74,1092,128],{"class":80},[74,1094,192],{"class":134},[74,1096,138],{"class":84},[14,1098,1099],{},[310,1100,1101],{},"Operational Impact:",[314,1103,1104,1115],{},[317,1105,1106,1108,1109,1111,1112,1114],{},[32,1107,1022],{}," vs ",[32,1110,1054],{}," behavior diverges significantly in V2. ",[32,1113,1022],{}," respects the instantiation boundary, making it safer for partial updates.",[317,1116,1117,1118,1121,1122,1126],{},"Nested object graphs are serialized iteratively in Rust. For deeply recursive structures, monitor memory allocation and consider ",[32,1119,1120],{},"model_dump(exclude={\"deeply_nested_field\"})"," to prevent OOM spikes. Reference ",[18,1123,1125],{"href":1124},"\u002Fadvanced-pydantic-validation-serialization\u002Fnested-model-serialization\u002F","Nested Model Serialization"," for optimization patterns when handling large payload trees in high-throughput APIs.",[24,1128,1130],{"id":1129},"api-stability-backward-compatibility","API Stability & Backward Compatibility",[14,1132,1133,1134,1136,1137,1108,1139,222,1142,1145,1146,1149],{},"Pydantic V2 generates stricter JSON Schema definitions by default. ",[32,1135,321],{}," is now the implicit baseline for many configurations, and type representations (e.g., ",[32,1138,300],{},[32,1140,1141],{},"number",[32,1143,1144],{},"string"," formats) have been standardized. FastAPI 0.100+ natively supports V2, but automatic schema generation may break downstream clients expecting legacy ",[32,1147,1148],{},"additionalProperties: true"," or lenient type coercion.",[45,1151,1153],{"id":1152},"phased-rollout-architecture","Phased Rollout Architecture",[14,1155,1156,1157,1160],{},"To achieve zero-downtime migrations, isolate V2 models behind versioned routes or feature flags. Use ",[32,1158,1159],{},"pydantic.v1"," compatibility shims only as a temporary bridge, as they incur double-validation overhead.",[65,1162,1164],{"className":67,"code":1163,"language":69,"meta":70,"style":70},"from fastapi import FastAPI, Depends\nfrom pydantic import ValidationError\nfrom typing import Dict, Any\n\napp = FastAPI()\n\n@app.post(\"\u002Fapi\u002Fv2\u002Forders\")\nasync def create_order(payload: OrderPayload):\n try:\n # Validation occurs synchronously at the dependency layer\n # FastAPI automatically maps ValidationError to 422 responses\n return {\"status\": \"accepted\", \"sku\": payload.sku}\n except ValidationError as e:\n # Structured error logging for observability\n logger.error(\"Validation failure\", extra={\"errors\": e.errors()})\n raise\n",[32,1165,1166,1178,1189,1200,1204,1214,1218,1230,1243,1250,1255,1260,1282,1296,1301,1324],{"__ignoreMap":70},[74,1167,1168,1170,1173,1175],{"class":76,"line":77},[74,1169,81],{"class":80},[74,1171,1172],{"class":84}," fastapi ",[74,1174,88],{"class":80},[74,1176,1177],{"class":84}," FastAPI, Depends\n",[74,1179,1180,1182,1184,1186],{"class":76,"line":94},[74,1181,81],{"class":80},[74,1183,85],{"class":84},[74,1185,88],{"class":80},[74,1187,1188],{"class":84}," ValidationError\n",[74,1190,1191,1193,1195,1197],{"class":76,"line":107},[74,1192,81],{"class":80},[74,1194,99],{"class":84},[74,1196,88],{"class":80},[74,1198,1199],{"class":84}," Dict, Any\n",[74,1201,1202],{"class":76,"line":115},[74,1203,119],{"emptyLinePlaceholder":118},[74,1205,1206,1209,1211],{"class":76,"line":122},[74,1207,1208],{"class":84},"app ",[74,1210,128],{"class":80},[74,1212,1213],{"class":84}," FastAPI()\n",[74,1215,1216],{"class":76,"line":141},[74,1217,119],{"emptyLinePlaceholder":118},[74,1219,1220,1223,1225,1228],{"class":76,"line":146},[74,1221,1222],{"class":152},"@app.post",[74,1224,156],{"class":84},[74,1226,1227],{"class":218},"\"\u002Fapi\u002Fv2\u002Forders\"",[74,1229,138],{"class":84},[74,1231,1232,1235,1237,1240],{"class":76,"line":165},[74,1233,1234],{"class":80},"async",[74,1236,495],{"class":80},[74,1238,1239],{"class":152}," create_order",[74,1241,1242],{"class":84},"(payload: OrderPayload):\n",[74,1244,1245,1248],{"class":76,"line":172},[74,1246,1247],{"class":80}," try",[74,1249,511],{"class":84},[74,1251,1252],{"class":76,"line":183},[74,1253,1254],{"class":168}," # Validation occurs synchronously at the dependency layer\n",[74,1256,1257],{"class":76,"line":198},[74,1258,1259],{"class":168}," # FastAPI automatically maps ValidationError to 422 responses\n",[74,1261,1262,1264,1267,1270,1272,1275,1277,1279],{"class":76,"line":210},[74,1263,624],{"class":80},[74,1265,1266],{"class":84}," {",[74,1268,1269],{"class":218},"\"status\"",[74,1271,248],{"class":84},[74,1273,1274],{"class":218},"\"accepted\"",[74,1276,222],{"class":84},[74,1278,471],{"class":218},[74,1280,1281],{"class":84},": payload.sku}\n",[74,1283,1284,1287,1290,1293],{"class":76,"line":228},[74,1285,1286],{"class":80}," except",[74,1288,1289],{"class":84}," ValidationError ",[74,1291,1292],{"class":80},"as",[74,1294,1295],{"class":84}," e:\n",[74,1297,1298],{"class":76,"line":257},[74,1299,1300],{"class":168}," # Structured error logging for observability\n",[74,1302,1303,1306,1309,1311,1314,1316,1318,1321],{"class":76,"line":263},[74,1304,1305],{"class":84}," logger.error(",[74,1307,1308],{"class":218},"\"Validation failure\"",[74,1310,222],{"class":84},[74,1312,1313],{"class":186},"extra",[74,1315,128],{"class":80},[74,1317,236],{"class":84},[74,1319,1320],{"class":218},"\"errors\"",[74,1322,1323],{"class":84},": e.errors()})\n",[74,1325,1326],{"class":76,"line":268},[74,1327,1328],{"class":80}," raise\n",[14,1330,1331],{},[310,1332,1333],{},"Schema Alignment Checklist:",[314,1335,1336,1346,1361],{},[317,1337,1338,1339,59,1342,1345],{},"Audit ",[32,1340,1341],{},"json_schema_extra",[32,1343,1344],{},"Field(description=...)"," to ensure OpenAPI documentation matches client expectations.",[317,1347,1348,1349,1352,1353,1356,1357,1360],{},"If legacy clients require ",[32,1350,1351],{},"additionalProperties",", explicitly set ",[32,1354,1355],{},"extra=\"allow\""," in ",[32,1358,1359],{},"model_config"," and document the deviation.",[317,1362,1363,1364,1368],{},"Implement contract testing against generated OpenAPI specs before merging migration PRs. For tactical deployment strategies that prevent client breakage during dependency upgrades, review ",[18,1365,1367],{"href":1366},"\u002Fadvanced-pydantic-validation-serialization\u002Fpydantic-v2-migration-guide\u002Fmigrating-from-pydantic-v1-to-v2-without-breaking-apis\u002F","Migrating from Pydantic v1 to v2 without breaking APIs",".",[24,1370,1372],{"id":1371},"common-migration-pitfalls","Common Migration Pitfalls",[1374,1375,1376,1392],"table",{},[1377,1378,1379],"thead",{},[1380,1381,1382,1386,1389],"tr",{},[1383,1384,1385],"th",{},"Pitfall",[1383,1387,1388],{},"Operational Impact",[1383,1390,1391],{},"Resolution",[1393,1394,1395,1427,1455,1476],"tbody",{},[1380,1396,1397,1408,1414],{},[1398,1399,1400],"td",{},[310,1401,1402,1403,59,1405,1407],{},"Assuming ",[32,1404,813],{},[32,1406,816],{}," persist",[1398,1409,1410,1413],{},[32,1411,1412],{},"AttributeError"," at runtime or silent fallback to slower Python serialization.",[1398,1415,1416,1417,1419,1420,1422,1423,1426],{},"Refactor all exports to ",[32,1418,820],{}," \u002F ",[32,1421,823],{},". Run ",[32,1424,1425],{},"grep -r \"\\.dict()|\\.json()\""," across the codebase.",[1380,1428,1429,1439,1446],{},[1398,1430,1431],{},[310,1432,1433,1434,1108,1437],{},"Misunderstanding ",[32,1435,1436],{},"mode='before'",[32,1438,368],{},[1398,1440,1441,1442,1445],{},"Validators bypass type coercion, causing ",[32,1443,1444],{},"TypeError"," or security bypasses on raw input.",[1398,1447,1448,1449,1451,1452,1454],{},"Default to ",[32,1450,368],{}," for business logic. Use ",[32,1453,1436],{}," strictly for normalization or format validation.",[1380,1456,1457,1462,1467],{},[1398,1458,1459],{},[310,1460,1461],{},"Ignoring strict mode defaults",[1398,1463,1464,1465,1368],{},"Legacy string-to-int or float coercion fails silently or raises ",[32,1466,328],{},[1398,1468,1469,1470,1356,1473,1475],{},"Explicitly set ",[32,1471,1472],{},"coerce_numbers_to_str=True",[32,1474,54],{}," if legacy behavior is required, or update client payloads.",[1380,1477,1478,1486,1489],{},[1398,1479,1480],{},[310,1481,1482,1483],{},"Overusing ",[32,1484,1485],{},"@model_validator(mode='before')",[1398,1487,1488],{},"Bypasses field-level validation, making debugging and schema generation unreliable.",[1398,1490,1491],{},"Prefer field-level validators. Use model validators only for cross-field dependencies.",[24,1493,1495],{"id":1494},"frequently-asked-questions","Frequently Asked Questions",[14,1497,1498],{},[310,1499,1500],{},"Does FastAPI automatically support Pydantic V2?",[14,1502,1503,1504,1507,1508,1510,1511,1514,1515,1517],{},"FastAPI 0.100+ includes native V2 support, but requires explicit dependency pinning (",[32,1505,1506],{},"pydantic>=2.0,\u003C3.0",") and response model updates. FastAPI's dependency injection layer automatically handles V2 ",[32,1509,328],{}," mapping to ",[32,1512,1513],{},"422 Unprocessable Entity",", but legacy response models relying on implicit ",[32,1516,813],{}," conversion will fail without refactoring.",[14,1519,1520],{},[310,1521,1522,1523,1525],{},"How do I handle ",[32,1524,345],{}," replacements?",[14,1527,1528,1529,1532,1533,1535,1536,1538,1539,1541,1542,1544],{},"Replace with ",[32,1530,1531],{},"@model_validator(mode=\"before\" | \"after\")",". The ",[32,1534,757],{}," variant receives the raw input dictionary, while ",[32,1537,770],{}," receives the fully instantiated model. Utilize the ",[32,1540,776],{}," object to access sibling fields and apply cross-field constraints without relying on deprecated ",[32,1543,780],{}," dictionaries.",[14,1546,1547],{},[310,1548,1549],{},"Will my existing OpenAPI schemas change after migration?",[14,1551,1552,1553,1555,1556,1558,1559,1561,1562,1565],{},"Yes. V2 enforces stricter JSON Schema generation, removing implicit ",[32,1554,1148],{}," and tightening type definitions. Review ",[32,1557,321],{}," defaults, custom ",[32,1560,1341],{}," configurations, and ",[32,1563,1564],{},"Field()"," metadata to maintain backward compatibility with external API consumers.",[14,1567,1568],{},[310,1569,1570],{},"Can I run V1 and V2 models concurrently?",[14,1572,1573,1574,1577],{},"Yes, via ",[32,1575,1576],{},"from pydantic.v1 import BaseModel"," for legacy routes. However, this incurs dual validation overhead and complicates dependency resolution. Use it strictly as a transitional shim during phased rollouts, and prioritize isolating V2 models behind versioned API endpoints to minimize runtime footprint.",[1579,1580,1581],"style",{},"html pre.shiki code .sD7c4, html code.shiki .sD7c4{--shiki-default:#D73A49}html pre.shiki code .sgsFI, html code.shiki .sgsFI{--shiki-default:#24292E}html pre.shiki code .sYu0t, html code.shiki .sYu0t{--shiki-default:#005CC5}html pre.shiki code .s7eDp, html code.shiki .s7eDp{--shiki-default:#6F42C1}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html pre.shiki code .sqxcx, html code.shiki .sqxcx{--shiki-default:#E36209}html pre.shiki code .sYBdl, html code.shiki .sYBdl{--shiki-default:#032F62}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":70,"searchDepth":94,"depth":94,"links":1583},[1584,1587,1590,1593,1596,1597],{"id":26,"depth":94,"text":27,"children":1585},[1586],{"id":47,"depth":107,"text":48},{"id":335,"depth":94,"text":336,"children":1588},[1589],{"id":372,"depth":107,"text":373},{"id":806,"depth":94,"text":807,"children":1591},[1592],{"id":831,"depth":107,"text":832},{"id":1129,"depth":94,"text":1130,"children":1594},[1595],{"id":1152,"depth":107,"text":1153},{"id":1371,"depth":94,"text":1372},{"id":1494,"depth":94,"text":1495},"Upgrading to Pydantic V2 is not a drop-in replacement; it is an architectural pivot that trades legacy Python-based introspection for a compiled Rust…","md",{},"\u002Fadvanced-pydantic-validation-serialization\u002Fpydantic-v2-migration-guide",{"title":5,"description":1598},"advanced-pydantic-validation-serialization\u002Fpydantic-v2-migration-guide\u002Findex","rwOXADGdIXSqLlME-6_chx3a7G5BtCiCDTjAXyEueME",[1606,1669],{"title":1607,"path":1608,"stem":1609,"children":1610,"page":-1},"Advanced Pydantic Validation Serialization","\u002Fadvanced-pydantic-validation-serialization","advanced-pydantic-validation-serialization",[1611,1613,1625,1637,1649,1655,1663],{"title":21,"path":1608,"stem":1612},"advanced-pydantic-validation-serialization\u002Findex",{"title":1614,"path":1615,"stem":1616,"children":1617,"page":-1},"Custom Validators & Field Constraints in FastAPI & Pydantic V2","\u002Fadvanced-pydantic-validation-serialization\u002Fcustom-validators-field-constraints","advanced-pydantic-validation-serialization\u002Fcustom-validators-field-constraints\u002Findex",[1618,1619],{"title":1614,"path":1615,"stem":1616},{"title":1620,"path":1621,"stem":1622,"children":1623},"Creating Reusable Custom Validators in Pydantic: Production Patterns","\u002Fadvanced-pydantic-validation-serialization\u002Fcustom-validators-field-constraints\u002Fcreating-reusable-custom-validators-in-pydantic","advanced-pydantic-validation-serialization\u002Fcustom-validators-field-constraints\u002Fcreating-reusable-custom-validators-in-pydantic\u002Findex",[1624],{"title":1620,"path":1621,"stem":1622},{"title":1626,"path":1627,"stem":1628,"children":1629,"page":-1},"JSON Schema Customization","\u002Fadvanced-pydantic-validation-serialization\u002Fjson-schema-customization","advanced-pydantic-validation-serialization\u002Fjson-schema-customization\u002Findex",[1630,1631],{"title":1626,"path":1627,"stem":1628},{"title":1632,"path":1633,"stem":1634,"children":1635},"Customizing OpenAPI Schema Generation in FastAPI: Production Implementation Guide","\u002Fadvanced-pydantic-validation-serialization\u002Fjson-schema-customization\u002Fcustomizing-openapi-schema-generation-in-fastapi","advanced-pydantic-validation-serialization\u002Fjson-schema-customization\u002Fcustomizing-openapi-schema-generation-in-fastapi\u002Findex",[1636],{"title":1632,"path":1633,"stem":1634},{"title":1638,"path":1639,"stem":1640,"children":1641,"page":-1},"Mastering Nested Model Serialization in FastAPI","\u002Fadvanced-pydantic-validation-serialization\u002Fnested-model-serialization","advanced-pydantic-validation-serialization\u002Fnested-model-serialization\u002Findex",[1642,1643],{"title":1638,"path":1639,"stem":1640},{"title":1644,"path":1645,"stem":1646,"children":1647},"Handling Deeply Nested JSON Models Efficiently in FastAPI","\u002Fadvanced-pydantic-validation-serialization\u002Fnested-model-serialization\u002Fhandling-deeply-nested-json-models-efficiently","advanced-pydantic-validation-serialization\u002Fnested-model-serialization\u002Fhandling-deeply-nested-json-models-efficiently\u002Findex",[1648],{"title":1644,"path":1645,"stem":1646},{"title":1650,"path":1651,"stem":1652,"children":1653},"Performance Optimization for Models in FastAPI","\u002Fadvanced-pydantic-validation-serialization\u002Fperformance-optimization-for-models","advanced-pydantic-validation-serialization\u002Fperformance-optimization-for-models\u002Findex",[1654],{"title":1650,"path":1651,"stem":1652},{"title":5,"path":1601,"stem":1603,"children":1656},[1657,1658],{"title":5,"path":1601,"stem":1603},{"title":1367,"path":1659,"stem":1660,"children":1661},"\u002Fadvanced-pydantic-validation-serialization\u002Fpydantic-v2-migration-guide\u002Fmigrating-from-pydantic-v1-to-v2-without-breaking-apis","advanced-pydantic-validation-serialization\u002Fpydantic-v2-migration-guide\u002Fmigrating-from-pydantic-v1-to-v2-without-breaking-apis\u002Findex",[1662],{"title":1367,"path":1659,"stem":1660},{"title":1664,"path":1665,"stem":1666,"children":1667},"Type Hinting & IDE Integration in FastAPI: Advanced Pydantic Patterns","\u002Fadvanced-pydantic-validation-serialization\u002Ftype-hinting-ide-integration","advanced-pydantic-validation-serialization\u002Ftype-hinting-ide-integration\u002Findex",[1668],{"title":1664,"path":1665,"stem":1666},{"title":1670,"path":1671,"stem":1672,"children":1673,"page":-1},"Core Architecture Routing Patterns","\u002Fcore-architecture-routing-patterns","core-architecture-routing-patterns",[1674,1677,1689,1701,1713,1725,1737],{"title":1675,"path":1671,"stem":1676},"Core Architecture & Routing Patterns in FastAPI: A Production-Ready Blueprint","core-architecture-routing-patterns\u002Findex",{"title":1678,"path":1679,"stem":1680,"children":1681,"page":-1},"Application Factory Patterns in FastAPI: Production Architecture Guide","\u002Fcore-architecture-routing-patterns\u002Fapplication-factory-patterns","core-architecture-routing-patterns\u002Fapplication-factory-patterns\u002Findex",[1682,1683],{"title":1678,"path":1679,"stem":1680},{"title":1684,"path":1685,"stem":1686,"children":1687},"FastAPI App Factory Pattern for Testing and Deployment: Production Guide","\u002Fcore-architecture-routing-patterns\u002Fapplication-factory-patterns\u002Ffastapi-app-factory-pattern-for-testing-and-deployment","core-architecture-routing-patterns\u002Fapplication-factory-patterns\u002Ffastapi-app-factory-pattern-for-testing-and-deployment\u002Findex",[1688],{"title":1684,"path":1685,"stem":1686},{"title":1690,"path":1691,"stem":1692,"children":1693},"Configuration Management in FastAPI: Production-Ready Patterns & Security","\u002Fcore-architecture-routing-patterns\u002Fconfiguration-management","core-architecture-routing-patterns\u002Fconfiguration-management\u002Findex",[1694,1695],{"title":1690,"path":1691,"stem":1692},{"title":1696,"path":1697,"stem":1698,"children":1699},"Managing Environment Variables with Pydantic Settings in FastAPI","\u002Fcore-architecture-routing-patterns\u002Fconfiguration-management\u002Fmanaging-environment-variables-with-pydantic-settings","core-architecture-routing-patterns\u002Fconfiguration-management\u002Fmanaging-environment-variables-with-pydantic-settings\u002Findex",[1700],{"title":1696,"path":1697,"stem":1698},{"title":1702,"path":1703,"stem":1704,"children":1705,"page":-1},"Dependency Injection Strategies","\u002Fcore-architecture-routing-patterns\u002Fdependency-injection-strategies","core-architecture-routing-patterns\u002Fdependency-injection-strategies\u002Findex",[1706,1707],{"title":1702,"path":1703,"stem":1704},{"title":1708,"path":1709,"stem":1710,"children":1711},"Best Practices for FastAPI Dependency Injection","\u002Fcore-architecture-routing-patterns\u002Fdependency-injection-strategies\u002Fbest-practices-for-fastapi-dependency-injection","core-architecture-routing-patterns\u002Fdependency-injection-strategies\u002Fbest-practices-for-fastapi-dependency-injection\u002Findex",[1712],{"title":1708,"path":1709,"stem":1710},{"title":1714,"path":1715,"stem":1716,"children":1717,"page":-1},"Error Handling & Global Exceptions in FastAPI","\u002Fcore-architecture-routing-patterns\u002Ferror-handling-global-exceptions","core-architecture-routing-patterns\u002Ferror-handling-global-exceptions\u002Findex",[1718,1719],{"title":1714,"path":1715,"stem":1716},{"title":1720,"path":1721,"stem":1722,"children":1723},"Global Exception Handlers for Consistent API Responses","\u002Fcore-architecture-routing-patterns\u002Ferror-handling-global-exceptions\u002Fglobal-exception-handlers-for-consistent-api-responses","core-architecture-routing-patterns\u002Ferror-handling-global-exceptions\u002Fglobal-exception-handlers-for-consistent-api-responses\u002Findex",[1724],{"title":1720,"path":1721,"stem":1722},{"title":1726,"path":1727,"stem":1728,"children":1729,"page":-1},"Middleware Implementation","\u002Fcore-architecture-routing-patterns\u002Fmiddleware-implementation","core-architecture-routing-patterns\u002Fmiddleware-implementation\u002Findex",[1730,1731],{"title":1726,"path":1727,"stem":1728},{"title":1732,"path":1733,"stem":1734,"children":1735},"Implementing Custom Middleware for Request Tracing in FastAPI","\u002Fcore-architecture-routing-patterns\u002Fmiddleware-implementation\u002Fimplementing-custom-middleware-for-request-tracing","core-architecture-routing-patterns\u002Fmiddleware-implementation\u002Fimplementing-custom-middleware-for-request-tracing\u002Findex",[1736],{"title":1732,"path":1733,"stem":1734},{"title":1738,"path":1739,"stem":1740,"children":1741,"page":-1},"Modular Router Organization in FastAPI: Production-Grade Architecture","\u002Fcore-architecture-routing-patterns\u002Fmodular-router-organization","core-architecture-routing-patterns\u002Fmodular-router-organization\u002Findex",[1742,1743],{"title":1738,"path":1739,"stem":1740},{"title":1744,"path":1745,"stem":1746,"children":1747},"How to Structure Large FastAPI Projects for Scale","\u002Fcore-architecture-routing-patterns\u002Fmodular-router-organization\u002Fhow-to-structure-large-fastapi-projects-for-scale","core-architecture-routing-patterns\u002Fmodular-router-organization\u002Fhow-to-structure-large-fastapi-projects-for-scale\u002Findex",[1748],{"title":1744,"path":1745,"stem":1746},[1750,1750],null,1778082654952]