python三方库_ciscoconfparse学习笔记
文章目录
- 介绍
- 使用
- 基本原理
- 父子关系
- 属性
- ioscfg 获取配置信息,返回列表
- is_config_line 判断是否是配置行
- is_intf 判断IOSCfgLine是不是interface
- is_subintf 判断IOSCfgLine是不是子接口
- lineage 不知道用法
- is_ethernet_intf 判断IOSCfgLine是否是以太网接口
- is_loopback_intf 判断IOSCfgLine是不是loopback接口
- intf_in_portchannel 判断接口是否在port-channel中
- portchannel_number 返回port-channel的序号
- 方法
- 实例
- 获取所有接口(interface)
- 获取包含特定配置的父配置
- 将接口名称和槽位建立关联
- 获取接口名称和接口描述
- 获取接口名称和IPv4地址
介绍
- 文档
- github
- 虽然项目名称为ciscoconfparse,但可以分析华为等格式类似的设备
- 安装
- 全新安装
pip3 install ciscoconfparse - 升级安装
pip3 install --upgrade ciscoconfparse - 安装指定版本
pip install ciscoconfparse==1.5.6
- 全新安装
使用
- 导入库
- 创建对象
- 代码
from ciscoconfparse import CiscoConfParse file1 = "/mnt/share/bak/pc1/share/IDC网络运维表格/备份文件/20210506/SW03.txt" cisco_cfg = CiscoConfParse(file1)
基本原理
父子关系
- 以缩进定义父子关系,
- 示例
policy-map QOS_1class GOLDpriority percent 10class SILVERbandwidth 30random-detectclass default ! - 示例说明
- 第1行为父级
- 第2 4 7 行为第1行的子级
- 第3行是第2行的子级
属性
ioscfg 获取配置信息,返回列表
- 返回的是list类型
- 示例
from ciscoconfparse import CiscoConfParse config = ['!','interface port-channel1',' ip address 112.54.105.38/30','!','interface Ethernet1/1',' channel-group 1 mode active',' no shutdown','interface Ethernet1/2',' no shutdown','!',] parse = CiscoConfParse(config) cfg = parse.ioscfg print(type(cfg)) print(cfg) - 示例输出
<class 'list'> ['!', 'interface port-channel1', ' ip address 112.54.105.38/30', '!', 'interface Ethernet1/1', ' channel- group 1 mode active', ' no shutdown', 'interface Ethernet1/2', ' no shutdown', '!']
is_config_line 判断是否是配置行
- 如果是配置行返回True
- 如果是空行、注释行么返回False
- 示例
from ciscoconfparse import CiscoConfParse config = ['interface Ethernet1/2',' no shutdown','!',] parse = CiscoConfParse(config) obj1 = parse.find_objects('^!')[0] obj2 = parse.find_objects('no shutdown')[0] print(obj1.is_config_line) print(obj2.is_config_line)
is_intf 判断IOSCfgLine是不是interface
- 返回的是布尔值
- 子接口也是接口
- 示例
from ciscoconfparse import CiscoConfParse config = ['!','interface Serial1/0',' ip address 1.1.1.1 255.255.255.252','!','interface ATM2/0',' no ip address','!','interface ATM2/0.100 point-to-point',' ip address 1.1.1.5 255.255.255.252',' pvc 0/100',' vbr-nrt 704 704','!',] parse = CiscoConfParse(config) obj = parse.find_objects('^interface\sSerial')[0] print(obj.is_intf) obj = parse.find_objects('^interface\sATM')[0] print(obj.is_intf)
is_subintf 判断IOSCfgLine是不是子接口
- 用法同上
lineage 不知道用法
is_ethernet_intf 判断IOSCfgLine是否是以太网接口
- 返回布尔值
- 任何以太网接口(10M到10G)都被视为以太网接口
- 示例
from ciscoconfparse import CiscoConfParse config = ['interface port-channel1',' no shutdown','!','interface Ethernet1/2',' no shutdown','!',] parse = CiscoConfParse(config) obj1 = parse.find_objects('interface port-channel1')[0] obj2 = parse.find_objects('interface Ethernet1/2')[0] print(obj1.is_ethernet_intf ) print(obj2.is_ethernet_intf ) - 示例输出
False True
is_loopback_intf 判断IOSCfgLine是不是loopback接口
- 判断是不是loopback接口
- 返回的是布尔值
- 示例
from ciscoconfparse import CiscoConfParse config = ['!','interface FastEthernet1/0',' ip address 1.1.1.1 255.255.255.252','!','interface Loopback0',' ip address 1.1.1.5 255.255.255.255','!',] parse = CiscoConfParse(config) obj = parse.find_objects(r'^interface\sFast')[0] print(obj.is_loopback_intf) obj = parse.find_objects(r'^interface\sLoop')[0] print(obj.is_loopback_intf)
intf_in_portchannel 判断接口是否在port-channel中
- 返回的是布尔值,表示接口是否在port-channel中
- 示例
from ciscoconfparse import CiscoConfParse config = ['!','interface port-channel1',' ip address 112.54.105.38/30','!','interface Ethernet1/1',' channel-group 1 mode active',' no shutdown','interface Ethernet1/2',' no shutdown','!',] parse = CiscoConfParse(config) interface1 = parse.find_objects('^interface Ethernet1/1') interface2 = parse.find_objects('^interface Ethernet1/2') print ("interface1:",interface1[0].intf_in_portchannel) print ("interface2:",interface2[0].intf_in_portchannel) - 示例输出
interface1: True interface2: False
portchannel_number 返回port-channel的序号
- 返回的是int类型
- 如果不属于任何port-channel,则返回-1
- 示例
from ciscoconfparse import CiscoConfParse config = ['interface port-channel1',' no shutdown','!','interface Ethernet1/1',' channel-group 2 mode active',' no shutdown','interface Ethernet1/2',' no shutdown','!',] parse = CiscoConfParse(config) obj1 = parse.find_objects('^interface Ethernet1/1')[0] obj2 = parse.find_objects('^interface Ethernet1/2')[0] print(obj1.portchannel_number) print(obj2.portchannel_number) - 示例输出
2 -1
方法
find_objects() 检索文本
- 在对象中查找特定文本
- 语法
配置对象.find_objects("文本内容(可用正则)") - 示例
- 查找cisco-nxos中所有trunk组
# 获取所有接口 interfaces = cisco_cfg.find_objects("^interface port-channel") # 打印索引值为3的接口 print(interfaces[3]) # 打印所有接口名称 for obj in interfaces:print(obj.text)
- 查找cisco-nxos中所有trunk组
find_objects_w_child在父对象中检索特定文本
- 在父对象中检索特定文本
- 语法
配置对象.find_objects_w_child(parentspec=r"父对象包含的文本", childspec=r"子对象中包含的文本") - 示例,获取所有二层接口(N7K为例)
# 获取所有二层接口 interfaces = cisco_cfg.find_objects_w_child(parentspec=r"^interface", childspec=r"switchport") # 打印所有接口名称 for obj in interfaces:print(obj.text)
re_match 使用regex搜索IOSCfgLine文本并返回整数索引处的正则表达式组
- 介绍
- 使用regex搜索IOSCfgLine文本并返回整数索引处的正则表达式组
- 语法
re_match(regex, group=1, default='') - 选项
选项 类型 说明 regex str字符串或python正则表达式,应该匹配。此正则表达式应包含括号,括号用于绑定匹配组 group int 一个整数,指定要返回的所需正则表达式组。组默认为1 default str 如果不匹配,则返回默认值。默认情况下,如果不匹配,则返回空字符串。 返回结果 str 正则表达式组匹配的文本;如果不匹配,则返回默认值。 - 示例,打印接口下的子网掩码
from ciscoconfparse import CiscoConfParse config = ['!','interface Serial1/0',' ip address 1.1.1.1 255.255.255.248','!','interface Serial1/1',' ip address 1.1.1.5 255.255.255.252','!',] parse = CiscoConfParse(config) for obj in parse.find_objects(r'ip\saddress'):netmask = obj.re_match(r'1\.1\.1\.5\s(\S+)') print("The netmask is", netmask) - 示例输出
The netmask is 255.255.255.252
re_match_iter_typed()获取配置的值
- 语法
re_match_iter_typed(regex, group=1, result_type=<class 'str'>, default='', untyped_default=False, recurse=False) - 选项
选项 说明 regex 字符串,字符串或python正则表达式,应该匹配。此正则表达式应包含括号,括号用于绑定匹配组 group 整数,一个整数,指定要返回的所需正则表达式组。组默认为1。 result_type 类型,一种类型(通常是str、int、float或IPv4Obj中的一种)。所有返回值都转换为结果类型,默认为str default 任意,如果不匹配,则返回默认值 untyped_default 布尔值,如果不希望键入默认值,请设置True - 示例
import re from ciscoconfparse import CiscoConfParse from ciscoconfparse.ccp_util import IPv4Obj config = ['!','interface Serial1/0',' ip address 1.1.1.1 255.255.255.252','!','interface Serial2/0',' ip address 1.1.1.5 255.255.255.252','!',] parse = CiscoConfParse(config) INTF_RE = re.compile(r'interface\s\S+') ADDR_RE = re.compile(r'ip\saddress\s(\S+\s+\S+)') for obj in parse.find_objects(INTF_RE):print("{} {}".format(obj.text, obj.re_match_iter_typed(ADDR_RE, result_type=IPv4Obj))) - 示例输出
interface Serial1/0 <IPv4Obj 1.1.1.1/30> interface Serial2/0 <IPv4Obj 1.1.1.5/30>
re_match_typed
- 语法
re_match_typed(regex, group=1, untyped_default=False, result_type=<class 'str'>, default='') - 选项
选项 类型 说明 regex str 字符串或python正则表达式,应该匹配。此正则表达式应包含括号,括号用于绑定匹配组 group int 一个整数,指定要返回的所需正则表达式组。组默认为1。 result_type type 一种类型(通常是str、int、float或IPv4Obj中的一种)。所有返回值都转换为结果类型,默认为str. default any 如果不匹配,则返回默认值 untyped_default bool 如果不希望键入默认值,请设置True 返回结果 result_type 正则表达式组匹配的文本;如果不匹配,则返回默认值。除非untyped\u default为True,否则所有值都转换为结果类型 - 示例
- 见实例"将接口名称和槽位建立关联"
re_search 使用regex搜索此IOSCfgLine的文本
- 语法
re_search(regex, default='') - 选项
选项 类型 说明 regex str 字符串或python正则表达式,应该匹配。 default str 如果在查找regex时re\u search()未找到匹配项,则返回的值 返回结果 str 匹配的IOSCfgLine文本。如果不匹配,则返回默认值 - 示例
re_search_children 使用regex搜索此子级中包含的文本
- 介绍
- 使用regex搜索此子级中包含的文本
- 语法
re_search_children(regex, recurse=False) - 选项
选项 类型 说明 regex str 字符串或python正则表达式 recurse bool 如果要搜索所有子级(子级、孙子级、曾孙级等),请设置为True 返回结果 list 匹配的IOSCfgLine对象的列表。如果没有匹配项,则返回空list() - 示例
from ciscoconfparse import CiscoConfParse config = ['!','interface Serial1/0',' ip address 1.1.1.1 255.255.255.252','!','interface Serial2/0',' ip address 1.1.1.5 255.255.255.252','!',] parse = CiscoConfParse(config) interfaces = parse.re_search_children(regex=r'^interface\s(\S+)', recurse=False) print(interfaces) - 示例输出
[<IOSCfgLine # 1 'interface Serial1/0'>, <IOSCfgLine # 4 'interface Serial2/0'>]
实例
获取所有接口(interface)
- 获取的是对象
- 每个接口名称使用.text属性
- 可基于interfaces的索引获取指定接口,获取的也是对象,接口名称是"对象.text"
- 代码
# 获取所有接口 interfaces = cisco_cfg.find_objects("^interface") # 打印索引值为3的接口(对象),接口名使用"对象.text" print(interfaces[3]) # 打印所有接口名称 for obj in interfaces:print(obj.text)
获取包含特定配置的父配置
- 获取no shutdown的接口
- 方法一效率更高
- 方法一
interfaces_All = cisco_cfg.find_objects(r"^interf") interfaces_AdminUp = list() for obj in interfaces_All:if obj.re_search_children(r"no shutdown"):interfaces_AdminUp.append(obj) print(interfaces_AdminUp) - 方法二
interface_NoShutdown = cisco_cfg.find_parents_w_child("^interface", "no shutdown") for i in interface_NoShutdown:print (i)
- 方法一
将接口名称和槽位建立关联
- 名称将转换为str(),槽将转换为int()
- 代码
from ciscoconfparse import CiscoConfParse config = ['!','interface Serial1/0',' ip address 1.1.1.1 255.255.255.252','!','interface Serial2/0',' ip address 1.1.1.5 255.255.255.252','!',] parse = CiscoConfParse(config) slots = dict() for obj in parse.find_objects(r'^interface'):name = obj.re_match_typed(regex=r'^interface\s(\S+)',default='UNKNOWN')slot = obj.re_match_typed(regex=r'Serial(\d+)',result_type=int,default=-1)print("Interface {0} is in slot {1}".format(name, slot))
获取接口名称和接口描述
- 代码
parse = CiscoConfParse(file1) for obj in parse.find_objects_w_child(parentspec=r"^interface", childspec=r"descript"):name = obj.textdesc = obj.re_match_iter_typed(r'description\s(.*)', result_type=str)print(name,desc)
获取接口名称和IPv4地址
- 支持同一接口下有多个IPv4地址
- 代码
from pathlib import Path from netaddr import IPNetwork from ciscoconfparse import CiscoConfParsefile = Path('/mnt/share/00temp/01_DongHuan/config/核心交换机.txt') #file = Path('/mnt/share/00temp/01_DongHuan/config/A508-xi-2.log') parse = CiscoConfParse(file) # 使用ip address 192.168.1.1/24格式的正则 REGEX_ip1 = r'ip\s+address\s+(\S+/\d{1,2})' # 使用ip address 192.168.1.1 255.255.255.0格式的正则 REGEX_ip2 = r'ip\s+address\s+(\S+[\s]\d+\S+)' # interface的正则 REGEX_interface = r'^interface\s+(\S+)' for intf_obj in parse.find_objects(REGEX_interface):interface_name = intf_obj.text.replace('interface ','')# 每个元素为一个IP地址IPv4s = list()for child_obj in intf_obj.children: # Iterate over intf children#print(child_obj.text)if '/' in child_obj.text:REGEX_ip = REGEX_ip1else:REGEX_ip = REGEX_ip2ipv4 = child_obj.re_match_typed(REGEX_ip)if ipv4:if " " in ipv4:ipv4 = ipv4.split()ipv4 = IPNetwork(f'{ipv4[0]}/{ipv4[1]}')IPv4s.append(str(ipv4))if IPv4s:# 显示接口有IPv4地址的接口名称,和IPv4(逗号分隔的ipv4地址)print(interface_name,','.join(IPv4s))
相关文章:
python三方库_ciscoconfparse学习笔记
文章目录 介绍使用基本原理父子关系 属性ioscfg 获取配置信息,返回列表is_config_line 判断是否是配置行is_intf 判断IOSCfgLine是不是interfaceis_subintf 判断IOSCfgLine是不是子接口lineage 不知道用法is_ethernet_intf 判断IOSCfgLine是否是以太网接口is_loopback_intf 判断…...
HDFS详解(Hadoop)
Hadoop 分布式文件系统(Hadoop Distributed File System,HDFS)是 Apache Hadoop 生态系统的核心组件之一,它是设计用于存储大规模数据集并运行在廉价硬件上的分布式文件系统。 1. 分布式存储: HDFS 将文件分割成若干块…...
python创建word文档并向word中写数据
一、docx库的安装方法 python创建word文档需要用到docx库,安装命令如下: pip install python-docx 注意,安装的是python-docx。 二、使用方法 使用方法有很多,这里只介绍创建文档并向文档中写入数据。 import docxmydocdocx.Do…...
MongoDB的安装配置及使用
文章目录 前言一、MongoDB的下载、安装、配置二、检验MongoDB是否安装成功三、Navicat 操作MongoDB四、创建一个集合,存放三个文档总结 前言 本文内容: 💫 MongoDB的下载、安装、配置 💫 检验MongoDB是否安装成功 ❤️ Navicat 操…...
Go学习路线
Go学习路线 文章目录 Go学习路线入门阶段一、Go基础和Goland的安装二、学习日志文件及配置文件三、学习mysql四、html,css,js快速入门五、写一个简单的前后端分离的记事本项目六、Linux快速入门七、Docker快速入门八、Git命令快速入门九、使用Docker打包…...
安全大脑与盲人摸象
21世纪是数字科技和数字经济爆发的时代,互联网正从网状结构向类脑模型进行进化,出现了结构和覆盖范围庞大,能够适应不同技术环境、经济场景,跨地域、跨行业的类脑复杂巨型系统。如腾讯、Facebook等社交网络具备的神经网络特征&…...
如何使用Git-Secrets防止将敏感信息意外上传至Git库
关于Git-Secrets Git-secrets是一款功能强大的开发安全工具,该工具可以防止开发人员意外将密码和其他敏感信息上传到Git库中。 Git-secrets首先会扫描提交的代码和说明,当与用户预先配置的正则表达式模式匹配时,便会阻止此次提交。该工具的优…...
Day 14 网络协议
常见网络设备:交换机 路由器 中继器 多协议网关(路由器的前身) 交换机:用于连接统一网络的设备,实现内网设备通信。 从广义上分为:局域网交换机,广域网交换机 从网络构成分为:接…...
msyql中SQL 错误 [1118] [42000]: Row size too large (> 8126)
场景: CREATE TABLE test-qd.eqtree (INSERT INTO test.eqtree (idocid VARCHAR(50) NULL,sfcode VARCHAR(50) NULL,sfname VARCHAR(50) NULL,sfengname VARCHAR(50) NULL,…… ) ENGINEInnoDB DEFAULT CHARSETutf8 COLLATEutf8_general_ci;或 alter table eqtre…...
实验六 智能手机互联网程序设计(微信程序方向)实验报告
实验目的和要求 请完成创建图片库应用,显示一系列预设的图片。 提供按钮来切换显示不同类别的图片。 二、实验步骤与结果(给出对应的代码或运行结果截图) 1.WXML <view> <button bindtap"showAll">所有图片</but…...
Linux环境下,让Jar项目多线程部署成为可能
欢迎来到我的博客,代码的世界里,每一行都是一个故事 Linux环境下,让Jar项目多线程部署成为可能 前言背景介绍使用sh脚本实现使用systemd来实现使用docker-compose实现 前言 在当今互联网时代,应用程序的高可用性和性能是至关重要…...
k8s调度场景
15个KUBERNETES调度情景实用指南 Kubernetes调度是确保集群中的Pod在适当节点上运行的关键组件。通过灵活配置调度策略,可以提高资源利用率、负载平衡和高可用性。 在本文中,我们将深入探讨一些实际的Kubernetes调度场景,并提供相应的配置示…...
基于小程序实现的餐饮外卖系统
作者主页:Java码库 主营内容:SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app等设计与开发。 收藏点赞不迷路 关注作者有好处 文末获取源码 技术选型 【后端】:Java 【框架】:spring…...
家居网购项目(手写分页)
文章目录 1.后台管理—分页显示1.程序框架图2.编写数据模型Page.java 3.编写dao层1.修改FurnDao增加方法 2.修改FurnDaoImpl增加方法 3.单元测试FurnDaoTest 4.编写service层1.修改FurnService增加方法 2.修改FurnServiceImpl增加方法3.单元测试FurnServiceTest 5.编写DataUtil…...
goland2024安装包(亲测可用)
目录 一、软件简介 二、软件下载 一、软件简介 Goland 是一款由 JetBrains 公司开发的集成开发环境(IDE),专门用于 Go 语言的开发。它提供了丰富的功能和工具,帮助开发者更高效地编写、调试和管理 Go 语言项目。 功能特点&#x…...
35、链表-LRU缓存
思路: 首先要了解LRU缓存的原理,首先定下容量,每次get请求和put请求都会把当前元素放最前/后面,如果超过容量那么头部/尾部元素就被移除,所以最近最少使用的元素会被优先移除,保证热点数据持续存在。 不管放…...
数据结构速成--栈
由于是速成专题,因此内容不会十分全面,只会涵盖考试重点,各学校课程要求不同 ,大家可以按照考纲复习,不全面的内容,可以看一下小编主页数据结构初阶的内容,找到对应专题详细学习一下。 目录 一…...
算法练习第15天|226.翻转二叉树
226.翻转二叉树 力扣链接https://leetcode.cn/problems/invert-binary-tree/description/ 题目描述: 给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。 示例 1: 输入:root [4,2,7,1,3,6,9] 输出&am…...
C#面向对象——封装、封装案例示例
C#面向对象——封装 什么是封装? (1)封装是将数据和操作数据的方法(行为)封装在一起。 (2)程序中封装的体现:属性,方法,类,接口,命名空间&#…...
【InternLM 实战营第二期-笔记3】茴香豆:搭建你的 RAG 智能助理
书生浦语是上海人工智能实验室和商汤科技联合研发的一款大模型,很高兴能参与本次第二期训练营,我也将会通过笔记博客的方式记录学习的过程与遇到的问题,并为代码添加注释,希望可以帮助到你们。 记得点赞哟(๑ゝω╹๑) 茴香豆:搭建…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...
srs linux
下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935,SRS管理页面端口是8080,可…...
Springboot社区养老保险系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,社区养老保险系统小程序被用户普遍使用,为方…...
JS设计模式(4):观察者模式
JS设计模式(4):观察者模式 一、引入 在开发中,我们经常会遇到这样的场景:一个对象的状态变化需要自动通知其他对象,比如: 电商平台中,商品库存变化时需要通知所有订阅该商品的用户;新闻网站中࿰…...
基于SpringBoot在线拍卖系统的设计和实现
摘 要 随着社会的发展,社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统,主要的模块包括管理员;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单…...
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...
快刀集(1): 一刀斩断视频片头广告
一刀流:用一个简单脚本,秒杀视频片头广告,还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农,平时写代码之余看看电影、补补片,是再正常不过的事。 电影嘛,要沉浸,…...
关于easyexcel动态下拉选问题处理
前些日子突然碰到一个问题,说是客户的导入文件模版想支持部分导入内容的下拉选,于是我就找了easyexcel官网寻找解决方案,并没有找到合适的方案,没办法只能自己动手并分享出来,针对Java生成Excel下拉菜单时因选项过多导…...
在 Spring Boot 项目里,MYSQL中json类型字段使用
前言: 因为程序特殊需求导致,需要mysql数据库存储json类型数据,因此记录一下使用流程 1.java实体中新增字段 private List<User> users 2.增加mybatis-plus注解 TableField(typeHandler FastjsonTypeHandler.class) private Lis…...
