当前位置: 首页 > article >正文

9 Pydantic复杂数据结构的处理

在构建现代 Web 应用时,我们往往需要处理复杂的输入和输出数据结构。例如,响应数据可能包含嵌套字典、列表、元组,甚至是多个嵌套对象。Pydantic 是一个强大的数据验证和序列化库,可以帮助我们轻松地处理这些复杂的数据结构,并通过自定义方法进行验证和转换。

本文将介绍如何使用 Pydantic 处理复杂数据结构,包括嵌套模型、嵌套字典、列表、元组等,及如何使用自定义方法进行数据验证。

1. Pydantic 简介

Pydantic 通过定义 Python 类并继承 BaseModel,使得开发者能够轻松定义数据模型并进行自动验证。Pydantic 支持多种数据类型,包括基本类型(如 intstr 等)和更复杂的类型(如 ListDictTuple、嵌套模型等)。

2. 嵌套模型

2.1 嵌套模型的定义

在许多应用场景中,数据往往具有层级结构。例如,一个订单可能包含多个商品项,每个商品项都有自己的名称、数量和价格。我们可以通过嵌套 Pydantic 模型来处理这种层级结构。

假设我们有以下数据结构:一个订单包含用户信息和多个商品项。我们可以定义两个模型,UserItem,并在 Order 模型中嵌套这两个模型。

from pydantic import BaseModel
from typing import Listclass Item(BaseModel):name: strquantity: intprice: floatclass User(BaseModel):name: stremail: strclass Order(BaseModel):user: Useritems: List[Item]total_amount: float

在这个例子中:

  • Order 模型嵌套了 UserItem 模型。
  • items 字段是一个 Item 对象的列表,表示订单中的多个商品项。
  • total_amount 字段表示订单总金额。

2.2 使用嵌套模型

我们可以像下面这样创建一个订单对象:

order_data = {"user": {"name": "John Doe", "email": "john.doe@example.com"},"items": [{"name": "Laptop", "quantity": 1, "price": 1200.00},{"name": "Mouse", "quantity": 2, "price": 25.50}],"total_amount": 1251.00
}order = Order(**order_data)
print(order)

输出将是:

user=User(name='John Doe', email='john.doe@example.com') 
items=[Item(name='Laptop', quantity=1, price=1200.0), Item(name='Mouse', quantity=2, price=25.5)] 
total_amount=1251.0

2.3 嵌套字典和列表

Pydantic 模型也可以处理嵌套字典和列表结构。假设我们有一个场景,其中每个商品项可能包含多个属性,如商品的属性信息。

from typing import Dictclass Item(BaseModel):name: strquantity: intprice: floatattributes: Dict[str, str]  # 商品的额外属性class Order(BaseModel):user: Useritems: List[Item]total_amount: float

在这种情况下,attributes 字段是一个字典,存储商品的属性信息,如颜色、尺寸等。

order_data = {"user": {"name": "John Doe", "email": "john.doe@example.com"},"items": [{"name": "Laptop", "quantity": 1, "price": 1200.00, "attributes": {"color": "black", "size": "15 inch"}},{"name": "Mouse", "quantity": 2, "price": 25.50, "attributes": {"color": "red", "wireless": "yes"}}],"total_amount": 1251.00
}order = Order(**order_data)
print(order)

2.4 处理元组和其他数据类型

Pydantic 同样支持验证元组、集合等数据类型。我们可以使用 Tuple 来验证数据。

from typing import Tupleclass Order(BaseModel):user: Useritems: List[Item]total_amount: floatstatus: Tuple[str, str]  # 状态元组:订单状态和配送状态

在上面的代码中,status 是一个元组,包含两个字符串,分别表示订单的状态和配送状态。

3. 数据验证的自定义方法

Pydantic 允许我们为模型字段添加自定义验证方法,这使得我们可以根据特定规则对数据进行进一步验证。

3.1 使用 @validator 装饰器进行字段验证

假设我们需要验证订单总金额 total_amount,确保它不小于所有商品项的总价格。我们可以使用 @root_validator 装饰器来实现这个逻辑。

from pydantic import root_validator, ValidationErrorclass Order(BaseModel):user: Useritems: List[Item]total_amount: float@root_validatordef check_total_amount(cls, values):items = values.get('items')total_amount = values.get('total_amount')if items and total_amount:total_price = sum(item.quantity * item.price for item in items)if total_amount < total_price:raise ValueError('Total amount cannot be less than the sum of item prices.')return values

3.2 示例验证

假设我们创建一个订单,其中 total_amount 小于所有商品项的总价格:

order_data = {"user": {"name": "John Doe", "email": "john.doe@example.com"},"items": [{"name": "Laptop", "quantity": 1, "price": 1200.00},{"name": "Mouse", "quantity": 2, "price": 25.50}],"total_amount": 1000.00
}try:order = Order(**order_data)
except ValidationError as e:print(e)

输出将是:

1 validation error for Order
__root__Total amount cannot be less than the sum of item prices. (type=value_error)

Pydantic 会自动执行这个验证,并返回详细的错误信息。

3.3 验证嵌套模型中的数据

你还可以为嵌套的模型添加自定义验证。例如,我们可以确保用户的邮箱地址包含 @ 符号:

class User(BaseModel):name: stremail: str@validator('email')def validate_email(cls, value):if '@' not in value:raise ValueError('Email must contain "@" symbol')return value

这样,如果用户的邮箱地址没有 @ 符号,Pydantic 会自动抛出验证错误。

Pydantic 提供了强大的数据验证功能,帮助开发者轻松处理复杂的输入和输出数据结构。通过嵌套模型、字典、列表、元组等类型的支持,Pydantic 使得数据处理更加灵活和易于管理。同时,自定义的验证方法(如 @validator@root_validator)允许开发者根据业务逻辑定制数据验证规则,确保数据的正确性和一致性。

在使用 Pydantic 时,通过合理的模型设计和验证方法,可以提高代码的可读性、可维护性和健壮性。如果你正在构建需要复杂数据结构验证的应用,Pydantic 是一个非常值得依赖的工具。
在这里插入图片描述

相关文章:

9 Pydantic复杂数据结构的处理

在构建现代 Web 应用时&#xff0c;我们往往需要处理复杂的输入和输出数据结构。例如&#xff0c;响应数据可能包含嵌套字典、列表、元组&#xff0c;甚至是多个嵌套对象。Pydantic 是一个强大的数据验证和序列化库&#xff0c;可以帮助我们轻松地处理这些复杂的数据结构&#…...

C++ decltype 规则推导

C decltype 规则推导 文章目录 C decltype 规则推导**1. 基本规则****(1) 如果 decltype 的参数是变量名&#xff08;无括号的标识符&#xff09;****(2) 如果 decltype 的参数是表达式&#xff08;带括号或操作符&#xff09;** **2. 与 auto 的区别****3. 特殊场景****(1) 函…...

Rust 测试组织指南:单元测试与集成测试

一、为什么要同时使用单元测试与集成测试 单元测试&#xff1a;更为精细、聚焦某一逻辑单元&#xff1b;可以调用到私有函数&#xff0c;快速定位错误根源。集成测试&#xff1a;作为“外部代码”来使用库的公开接口&#xff0c;测试多个模块间的交互&#xff0c;确保整体功能…...

Day62_补20250210_图论part6_108冗余连接|109.冗余连接II

Day62_20250210_图论part6_108冗余连接|109.冗余连接II 108冗余连接 【把题意转化为并查集问题】 题目 有一个图&#xff0c;它是一棵树&#xff0c;他是拥有 n 个节点&#xff08;节点编号1到n&#xff09;和 n - 1 条边的连通无环无向图&#xff08;其实就是一个线形图&am…...

kafka消费端之消费者协调器和组协调器

文章目录 概述回顾历史老版本获取消费者变更老版本存在的问题 消费者协调器和组协调器新版如何解决老版本问题再均衡过程**第一阶段CFIND COORDINATOR****第二阶段&#xff08;JOINGROUP&#xff09;**选举消费组的lcader选举分区分配策略 第三阶段&#xff08;SYNC GROUP&…...

语法备忘04:将 事件处理函数 绑定到 组件 的事件上

示例1&#xff1a;<Table OnQueryAsync"OnQueryAsync" /> 示例2&#xff1a;<Table OnQueryAsync"OnQueryAsync" /> 说明&#xff1a;这两种写法在功能上是‌完全相同的‌&#xff0c;都是在将 OnQueryAsync 事件处理函数绑定到 Table 组件的 …...

C++20中的std::atomic_ref

一、std::atomic_ref 我们在学习C11后的原子操作时&#xff0c;都需要提前定义好std::atomic变量&#xff0c;然后才可以在后续的应用程序中进行使用。原子操作的优势在很多场合下优势非常明显&#xff0c;所以这也使得很多开发者越来习惯使用原子变量。 但是&#xff0c;在实…...

CSS 相关知识

1、高度已知&#xff0c;三栏布局&#xff0c;左右宽度 200&#xff0c;中间自适应&#xff0c;如何实现&#xff1f; <body><div class"box"><div class"box1">高度已知</div><div class"box2">左右宽度 200&…...

RocketMQ、RabbitMQ、Kafka 的底层实现、功能异同、应用场景及技术选型分析

1️⃣ 引言 在现代分布式系统架构中&#xff0c;&#x1f4e9;消息队列&#xff08;MQ&#xff09;是不可或缺的组件。它在系统&#x1f517;解耦、&#x1f4c9;流量削峰、⏳异步处理等方面发挥着重要作用。目前&#xff0c;主流的消息队列系统包括 &#x1f680;RocketMQ、&…...

IDEA升级出现问题Failed to prepare an update Temp directory inside installation

IDEA升级出现问题"Failed to prepare an update Temp directory inside installation…" 问题来源&#xff1a; 之前修改了IDEA的默认配置文件路径&#xff0c;然后升级新版本时就无法升级&#xff0c;提示"Failed to prepare an update Temp directory insid…...

DeepSeek提示词手册

一、核心原则&#xff1a;基于DeepSeek的推理特性 自然语言优先undefinedDeepSeek擅长理解自然表达&#xff0c;无需复杂模板。例如&#xff1a; ❌旧模板&#xff1a;"你是专业分析师&#xff0c;需分三步回答&#xff0c;第一步…" ✅高效提问&#xff1a;"…...

基于UVM搭验证环境

基于UVM搭验证环境基本思路&#xff1a; 首先&#xff0c;我们搭建环境时一般都有一个目标的DUT。此时&#xff0c;我们可以结合所要验证的的模块、是否需要VIP、验证侧重点等在典型的UVM验证环境的基础上做适当调整后形成一个大体的环境架构。比如&#xff0c;需要一个ahb_vip…...

C++性能优化—人工底稿版

C以高性能著称&#xff0c;性能优化是C程序员绕不过去的一个话题&#xff0c;性能优化是一个复杂、全局而又细节的问题&#xff0c;本文总结C性能分析中常用的知识。 性能优化的时机 大部分关于性能优化的文章都强调&#xff1a;不要过早的进行性能优化。 C编码层面 数据结…...

Java 使用腾讯翻译 API 实现含 HTML 标签文本精准翻译工具

一、翻译标签文本工具 package org.springblade.common.utils;import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern;public class TencentTranslationForHTML {public static void main(String[] args) {Stri…...

十款开源的论坛建站工具

以下是十款开源的论坛建站工具&#xff0c;它们各具特色&#xff0c;能够满足不同用户的需求&#xff1a; Discuz!&#xff08;Crossday Discuz! Board&#xff09; 特点&#xff1a;基础架构采用web编程组合PHPMySQL&#xff0c;用户可以在不需要任何编程的基础上&#xff0c;…...

vue学习6

1. 智慧商城 1. 路由设计配置 单个页面&#xff0c;独立展示的&#xff0c;是一级路由 2.二级路由配置 规则&组件配置导航链接配置路由出口 <template><div id"app"><!--二级路由出口--><router-view></router-view><van-…...

线程池以及日志、线程总结

一、线程池以及日志 1、基础线程池写法 主线程在main函数中构建一个线程池&#xff0c;初始化(Init)后开始工作(Start) 此时线程池中每个线程都已经工作起来了&#xff0c;只是任务队列中任务为空&#xff0c;所有线程处于休眠状态(通过线程同步中的条件变量实现&#xff0c…...

Vue 响应式渲染 - 过滤应用

Vue 渐进式JavaScript 框架 基于Vue2的学习笔记 - Vue响应式渲染综合 - 过滤应用 目录 过滤应用 引入vue Vue设置 设置页面元素 模糊查询过滤实现 函数表达式实现 总结 过滤应用 综合响应式渲染做一个输入框&#xff0c;用来实现&#xff1b;搜索输入框关键词符合列表。…...

【ThreeJS Basics 1-3】Hello ThreeJS,实现第一个场景

文章目录 环境创建一个项目安装依赖基础 Web 页面概念解释编写代码运行项目 环境 我的环境是 node version 22 创建一个项目 首先&#xff0c;新建一个空的文件夹&#xff0c;然后 npm init -y , 此时会快速生成好默认的 package.json 安装依赖 在新建的项目下用 npm 安装依…...

银行国际结算

银行国结项目&#xff0c;即国际结算项目&#xff0c;是银行业务中的重要组成部分&#xff0c;它涉及跨国界的货币收付和资金转移。 一、银行国结项目的定义 银行国结项目是指银行为国际贸易、投资等活动提供的国际结算服务&#xff0c;包括各种国际支付和资金清算业务。这些…...

Go语言构建微服务:从入门到实战

引言 在云原生时代&#xff0c;微服务架构已成为构建复杂分布式系统的首选方案。Go语言凭借其卓越的并发支持、简洁的语法和高效的运行时&#xff0c;成为微服务开发的利器。本文将深入探讨如何用Go构建健壮的微服务系统&#xff0c;并通过完整案例演示关键实现细节。 一、微…...

深入理解动态代理

为什么需要动态代理 对于代码的增强逻辑我们是清楚具体实现的,一种方式是增强逻辑作为委托类,被其他业务类调用, 这样会有很多重复代码,而且,当需要根据动态参数来决定增强逻辑时,重复代码会更多,逻辑会更不清晰 二,也是动态代理产生的原始需求,解决类爆照问题, 所以…...

私有属性和方法(python)

一、私有属性&#xff08;属性名前面加两个短下划线&#xff09; &#xff08;一&#xff09;私有属性与公有属性区别 公有属性&#xff1a;在类里面和外面均可以访问和修改 私有属性&#xff1a;需要用set方法才能修改&#xff0c;get方法才能访问 &#xff08;二&#xf…...

Cherry Studio之DeepSeek联网/本地,建属于自己的AI助理!

上一篇文章&#xff0c;讲了DeepSeek-R1部署到本地的方法。这一篇文章&#xff0c;我们让DeepSeek再一次升级&#xff0c;通过图形化界面来交互&#xff0c;从而变成我们的AI助理&#xff0c;让DeepSeek R1发挥最大实力&#xff01; 首选需要借助硅基流动的API接口&#xff0c…...

TcpClientTest

ClientTest&#xff1a; using System; using System.Net.Sockets; using System.Text;class TcpClientTest {static void Main(string[] args){try{// 创建一个TcpClient实例并连接到服务器 TcpClient client new TcpClient("1vg5062570.51mypc.cn", 43319);//1v…...

IGBT的两级关断

IGBT&#xff08;绝缘栅双极型晶体管&#xff09;的两级关断&#xff08;Two-stage turn-off&#xff09;是一种优化关断过程的方法&#xff0c;主要用于减少关断时的电压过冲和dv/dt&#xff08;电压变化率&#xff09;过高的问题&#xff0c;特别是在大功率应用中&#xff08…...

【STM32】ADC

本次实现的是ADC实现数字信号与模拟信号的转化&#xff0c;数字信号时不连续的&#xff0c;模拟信号是连续的。 1.ADC转化的原理 模拟-数字转换技术使用的是逐次逼近法&#xff0c;使用二分比较的方法来确定电压值 当单片机对应的参考电压为3.3v时&#xff0c;0~ 3.3v(模拟信号…...

从MyBatis-Plus看Spring Boot自动配置原理

一、问题引入&#xff1a;神秘的配置生效之谜 当我们使用MyBatis-Plus时&#xff0c;只需在pom.xml中添加依赖&#xff1a; <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3…...

0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 0基础…...

雪花算法应用

什么是雪花算法&#xff1f; 雪花算法是由 Twitter 开源的分布式 ID 生成算法&#xff0c;用于生成 64 位的长整型唯一 ID。其结构如下&#xff1a; - 1 位符号位&#xff1a;始终为 0 - 41 位时间戳&#xff1a;精确到毫秒 - 10 位工作机器 ID&#xff1a;包含 5 位数据中心 …...