第31节课 JSON数据解析

1.JSON基础概念

JSON 是一种轻量级的数据交换格式(另一个叫XML),具有简洁、易读的特点,并且在不同编程语言之间能很好地实现数据传递。在 Python 中,json模块能够实现 Python 数据类型与 JSON 数据格式之间的相互转换。

JSON的语法规则

  • 数据以键值对形式表示: "name": "张三"
  • 数据由逗号分隔
  • 花括号 {} 保存对象
  • 方括号 [] 保存数组
  • 支持的数据类型:
    • 数字(整数或浮点数)
    • 字符串(双引号中)
    • 布尔值(true 或 false)
    • 数组(方括号中)
    • 对象(花括号中)
    • null(None)
JSON 类型Python 类型
对象dict
数组list/tuple
字符串str
数字int/float
trueTrue
falseFalse
nullNone

JSON数据示例

{"name": "张三","age": 30,"isStudent": false,"courses": ["Python", "数据分析", "机器学习"],"address": {"city": "北京","postcode": "100000"},"phoneNumbers": null
}

json模块中的主要函数

函数描述
json.dumps()将Python对象编码成JSON字符串
json.dump()将Python对象编码成JSON字符串并写入文件
json.loads()将JSON字符串解码为Python对象
json.load()从文件中读取JSON字符串并解码为Python对象

2.JSON数据编码(序列化)

在实际开发中,为了让生成的 JSON 字符串更易读,可以使用indent参数进行缩进格式化,使用sort_keys参数按键名进行排序。

import json# 字典对象
data = {"name": "张三","age": 30,"isStudent": False,"courses": ["Python", "数据分析", "机器学习"],"address": {"city": "北京","postcode": "100000"},"phoneNumbers": None
}
# 将Python对象编码为JSON字符串
json_str = json.dumps(data, ensure_ascii=False)
print(json_str)
# 格式化输出
json_str = json.dumps(data, indent=4, ensure_ascii=False)
print(json_str)
json_str = json.dumps(data, indent=4, sort_keys=True, ensure_ascii=False)
print(json_str)# 写入到文件中
with open("data.json", "w", encoding="utf-8") as file:json.dump(data, file, ensure_ascii=False, indent=4, sort_keys=True)

3.JSON数据解码(反序列化)

import json
json_str = '{"name": "张三", "age": 30, "isStudent": false, "courses": ["Python", "数据分析", "机器学习"], "address": {"city": "北京", "postcode": "100000"}, "phoneNumbers": null}'
data = json.loads(json_str)
print(type(data))
print(data)
print(data['name'])
print(data['courses'][1])with open("data.json", 'r', encoding='utf-8') as file:data = json.load(file)print(data)print(type(data))

4.自定义编码器与解码器

标准的JSON只支持以下数据类型:

  • 字符串(string)
  • 数字(number)
  • 对象(object)- 在Python中表示为字典
  • 数组(array)- 在Python中表示为列表
  • 布尔值(boolean)- 在Python中表示为True/False
  • 空值(null)- 在Python中表示为None

然而,Python中有许多其他数据类型(如日期时间、自定义类、集合等)无法直接被JSON序列化。这就是为什么我们需要自定义编码器和解码器。

import json
import datetime
data = {"name": "张三","create_at": datetime.datetime.now(),"tags": {"Pythion", "JSON", "编程"}
}json_str = json.dumps(data, indent=4)
print(json_str)
# TypeError: Object of type set is not JSON serializable

自定义编码器

就是将Python中不能够直接编码为JSON格式的数据进行转换 转换成能够被JSON识别的数据

(1)使用default参数

最简单的自定义编码方式是使用 json.dumps() 的 default 参数:

import json
import datetime
data = {"name": "张三","create_at": datetime.datetime.now(),"tags": {"Pythion", "JSON", "编程"}
}# 编码函数:将非JSON类型的数据转换为JSON类型的数据
def custom_encoder(obj):if isinstance(obj, datetime.datetime):return obj.isoformat()elif isinstance(obj, set):return list(obj)json_str = json.dumps(data, indent=4, default=custom_encoder, ensure_ascii=False)
print(json_str)

(2)创建JSONEncoder子类

更灵活的方法是继承 json.JSONEncoder 类并重写 default 方法:

import json
import datetime
data = {"name": "张三","create_at": datetime.datetime.now(),"tags": {"Pythion", "JSON", "编程"}
}# 了解
class CustomJSONEncoder(json.JSONEncoder):def default(self, obj):if isinstance(obj, datetime.datetime):return {"__datetime__":True,"value":obj.isoformat()}elif isinstance(obj, set):return {"__set__": True, # 将数据原本的类型进行录入 为了给解码做提示"value":list(obj)}return super().default(obj)json_str = json.dumps(data, indent=4, cls=CustomJSONEncoder, ensure_ascii=False)
print(json_str)

自定义解码器

就是将某些JSON数据解码为原先的样子(Python数据类型)

(1)使用object_hook参数

json.loads() 函数的 object_hook 参数允许我们自定义JSON对象的解码方式:

import json
import datetime
json_str = """
{"name": "张三","create_at": {"__datetime__": true,"value": "2025-06-09T19:59:05.343916"},"tags": {"__set__": true,"value": ["编程","JSON","Pythion"]}
}
"""
# 自定义解码函数
def custom_decoder(obj):if "__datetime__" in obj:return datetime.datetime.fromisoformat(obj['value'])elif "__set__" in obj:return set(obj['value'])return objdata = json.loads(json_str, object_hook=custom_decoder)
print(data)

(2)创建JSONDecoder子类

更复杂的解码可以通过继承 json.JSONDecoder 类实现:

import json
import datetime
json_str = """
{"name": "张三","create_at": {"__datetime__": true,"value": "2025-06-09T19:59:05.343916"},"tags": {"__set__": true,"value": ["编程","JSON","Pythion"]}
}
"""
# 自定义解码类
class CustomJSONDecoder(json.JSONDecoder):# 构造函数def __init__(self, *args, **kwargs):json.JSONDecoder.__init__(self, object_hook=self.object_hook, *args, **kwargs)def object_hook(self,obj):if "__datetime__" in obj:return datetime.datetime.fromisoformat(obj['value'])elif "__set__" in obj:return set(obj['value'])return objdata = json.loads(json_str, cls=CustomJSONDecoder)
print(data)

5.处理复杂JSON数据

嵌套结构

{"company": "ABC科技","employees": [{"id": 1001,"name": "张三","department": "研发","skills": ["Python", "Django", "Docker"]},{"id": 1002,"name": "李四","department": "数据","skills": ["Python", "数据分析", "机器学习"]}],"address": {"city": "北京","street": "中关村","postcode": "100080"}
}
import json
json_str = '''
{"company": "ABC科技","employees": [{"id": 1001,"name": "张三","department": "研发","skills": ["Python", "Django", "Docker"]},{"id": 1002,"name": "李四","department": "数据","skills": ["Python", "数据分析", "机器学习"]}],"address": {"city": "北京","street": "中关村","postcode": "100080"}
}
'''
data = json.loads(json_str)
print(data['company'])
print(data['employees'][0]['name'])
print(data['employees'][1]['skills'][1])
for employee in data['employees']:print(employee['name'])print(employee['department'])print(employee['skills'])

动态解析路径

import json
json_str = '''
{"company": "ABC科技","employees": [{"id": 1001,"name": "张三","department": "研发","skills": ["Python", "Django", "Docker"]},{"id": 1002,"name": "李四","department": "数据","skills": ["Python", "数据分析", "机器学习"]}],"address": {"city": "北京","street": "中关村","postcode": "100080"}
}
'''
data = json.loads(json_str)path1 = "employees.0.name"
path2 = "address.city"def get_value_by_path(data, path):keys = path.split(".")result = datafor key in keys:if key.isdigit():result = result[int(key)]else:result = result[key]return resultprint(get_value_by_path(data, path1))
print(get_value_by_path(data, path2))
print(get_value_by_path(data, "employees.1.skills.2"))

6.拓展:jsonpath库

JSONPath提供了一种简洁的方式来导航JSON结构并提取特定数据,而不需要复杂的循环和条件语句。

pip install jsonpath-ng

基本语法元素

语法元素描述
$根对象/元素
@当前对象/元素
.子元素操作符
..递归下降操作符
*通配符,匹配所有对象/元素
[]下标操作符
[,]并集操作符
[start:end:step]数组切片操作符
?()过滤表达式
()脚本表达式

示例JSON数据

{"store": {"book": [{"category": "参考书","author": "李明","title": "Python编程入门","price": 49.99},{"category": "小说","author": "王芳","title": "梦想之旅","price": 29.99,"isbn": "0-553-21311-3"}],"bicycle": {"color": "红色","price": 599.99}}
}

示例路径演示

JSONPath描述
$.store.book[*].author所有书籍的作者
$..author所有作者
$.store.*store下的所有元素
$.store..pricestore下所有价格
$..book[2]第三本书
$..book[-1]最后一本书
$..book[0,1]前两本书
$..book[:2]前两本书
$..book[?(@.isbn)]所有有isbn属性的书
$..book[?(@.price<10)]所有价格小于10的书
$..book[?(@.price==8.95)]所有价格等于8.95的书
$..book[?(@.title =~ /.*REGEX.*/i)]标题匹配正则表达式的书

基本操作

import json
from jsonpath_ng import parse
json_str = """
{"store": {"book": [{"category": "参考书","author": "李明","title": "Python编程入门","price": 49.99},{"category": "小说","author": "王芳","title": "梦想之旅","price": 29.99,"isbn": "0-553-21311-3"}],"bicycle": {"color": "红色","price": 599.99}}
} """
data = json.loads(json_str)
# 导航对象
jsonpath_expr = parse('$.store.book[*].author')print(jsonpath_expr.find(data))# 列表
print(jsonpath_expr.find(data)[0]) # DatumInContext对象
print(type(jsonpath_expr.find(data)[0]))
for match in jsonpath_expr.find(data):print(match.value)print(match.path)print(match.context)

7.拓展:Schema验证

JSONSchema是一种用于验证JSON数据结构的规范,它允许我们定义JSON数据的格式、类型和约束条件,确保数据符合预期的结构和规则。

pip install jsonschema

JSONSchema是一种基于JSON格式的模式语言,用于:

  • 描述现有数据格式
  • 提供清晰的人机可读文档
  • 验证数据,确保数据质量
  • 自动测试和验证客户端提交的数据

核心关键字

关键字描述
$schema指定Schema的版本
titleSchema的标题
descriptionSchema的描述
type定义值的数据类型
properties定义对象的属性
required指定必需的属性
minimum/maximum数值的最小/最大值
minLength/maxLength字符串的最小/最大长度
pattern字符串必须匹配的正则表达式
enum枚举,值必须是指定的值之一
from jsonschema import validate# 定义一个JSON验证Schema
# 用户信息验证
user_schema = {"type": "object",  # 要求JSON整体是个JSON对象"properties": {  # 指定属性要求"name": {"type": "string"},  # 必须有一个name属性 string类型"age": {"type": "integer", "minimum": 0}, # 必须有一个age属性 int类型 最小0"email":{"type": "string", "format":"email"},"interests": {"type":"array", "items":{"type":"string"}}},"required":["name","age","email"]
}
user1  = {"name":"张三","age":30,"email":"zhangsan@qq.com","interests":["编程", "吃饭"]
}
user2  = {"name":"张三","age":30,"interests":["编程", "吃饭"]
}
user3 = {"name":"张三","age":30,"email":"zhangsan@qq.com",
}
user4 = {"name":"张三","age":"三十","email":"zhangsan@qq.com",
}
# 最好try-except
validate(instance=user1, schema=user_schema)
# validate(instance=user2, schema=user_schema) # 缺email
validate(instance=user3, schema=user_schema)
validate(instance=user4, schema=user_schema)

8.案例:头条新闻

import requestsdef print_news(title, uniquekey):# 1512-新闻详情查询 - 代码参考(根据实际业务情况修改)# 基本参数配置apiUrl = 'http://v.juhe.cn/toutiao/content'  # 接口请求URLapiKey = '3719af094e850cf3f4c4aea0bdb361d6'  # 在个人中心->我的数据,接口名称上方查看# 接口请求入参配置requestParams = {'key': apiKey,'uniquekey': uniquekey,}# 发起接口网络请求response = requests.get(apiUrl, params=requestParams)# 解析响应结果if response.status_code == 200:data = response.json()# 网络请求成功。可依据业务逻辑和接口文档说明自行处理。print("=" * 20)print(title)print(data['result']['content'])else:# 网络异常等因素,解析结果异常。可依据业务逻辑自行处理。print('请求异常')def search_news():# 923-新闻列表查询 - 代码参考(根据实际业务情况修改)# 基本参数配置apiUrl = 'http://v.juhe.cn/toutiao/index'  # 接口请求URLapiKey = '3719af094e850cf3f4c4aea0bdb361d6'  # 在个人中心->我的数据,接口名称上方查看# 接口请求入参配置requestParams = {'key': apiKey,'type': 'yule','page': 1,'page_size': 10,'is_filter': 0,}# 发起接口网络请求response = requests.get(apiUrl, params=requestParams)# 解析响应结果if response.status_code == 200:  # 404data = response.json()# 网络请求成功。可依据业务逻辑和接口文档说明自行处理。# print(data)# print(type(data))for item in data['result']['data']:print_news(item['title'], item['uniquekey'])else:# 网络异常等因素,解析结果异常。可依据业务逻辑自行处理。print('请求异常')search_news()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/95282.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/95282.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/95282.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于多模态大模型的个性化学习路径生成系统研究

摘要 随着互联网技术的迅猛发展&#xff0c;个性化学习路径生成系统的研究在教育领域日益凸显其重要性。本研究聚焦于基于多模态大模型的个性化学习路径生成系统&#xff0c;旨在通过整合多模态数据&#xff0c;为学习者提供更加精准、个性化的学习路径。多模态大模型&#xf…

ESP32 烧录固件失败原因排除

ESP32 烧录固件时&#xff0c;有哪些特殊引脚需要注意电平状态的在 ESP32 烧录固件时&#xff0c;有几个关键引脚的电平状态会直接影响烧录过程&#xff0c;需要特别注意&#xff1a;GPIO0&#xff08;BOOT 引脚&#xff09;&#xff1a;烧录模式&#xff1a;需要拉低&#xff…

3D视觉系统在机器人行业中的应用

视觉引导机器人技术&#xff08;VGR&#xff09;具有成熟的2D成像技术&#xff0c;但是经济高效的3D技术的出现使机器人应用的可能性更大。工业自动化的第一次迭代使用“盲”机器人&#xff0c;该机器人取决于待处理材料的精确定位。这样的机器人相对不灵活&#xff0c;只能通过…

MySQL高可用改造之数据库开发规范(大事务与数据一致性篇)

文章目录一、前言二、延迟的原因三、大事务处理规范3.1. 删除类操作优化设计3.2. 大事务通用拆分原则四、数据一致性核对规范4.1. 主从变更记录识别方法五、小结一、前言 MySQL 高可用架构中最基础、最为核心的内容&#xff1a;MySQL 复制&#xff08;Replication&#xff09;…

第9节 大模型分布式推理核心挑战与解决方案

文章目录 # 前言 一、通信瓶颈突破:让数据“跑”得更快 1. 问题:通信为什么会成为瓶颈? 2. 解决方案:从硬件到算法的全链路优化 (1)硬件层:升级“高速公路” (2)算法层:给数据“瘦身”并“错峰出行” (3)架构层:让数据“少跑路” 3. 效果评估:如何判断通信瓶颈已…

ESP32开发板接4阵脚屏幕教程(含介绍和针脚编号对应)

“4针屏幕” 一般有两种常见类型&#xff1a;IC 屏幕&#xff08;如 0.96" OLED、SSD1306 等&#xff09; 4 个针脚通常是&#xff1a;VCC → 接 ESP32 的 3.3V&#xff08;有的屏幕支持 5V&#xff09;GND → 接 ESP32 的 GNDSCL&#xff08;时钟&#xff09;→ 接 ESP32…

2025 年国内可用 Docker 镜像加速器地址

文章目录一、加速器地址搭建 Docker 镜像源二、使用一、加速器地址 docker.1ms.rundocker.domys.ccdocker.imgdb.dedocker-0.unsee.techdocker.hlmirror.comcjie.eu.orgdocker.m.daocloud.iohub.rat.devdocker.1panel.livedocker.rainbond.cc 搭建 Docker 镜像源 以上镜像源…

[Robotics_py] 路径规划算法 | 启发式函数 | A*算法

第五章&#xff1a;路径规划算法 欢迎回来&#xff0c;未来的机器人专家&#xff0d;&#xff1d;≡(・ω・) 在之前的章节中&#xff0c;我们已为机器人配备了核心知识&#xff1a;它能够跟踪自身的机器人状态/位姿&#xff0c;利用环境表示&#xff08;栅格地图&#xff09;理…

解决 HTTP 请求 RequestBody 只能被读取一次的问题

简介 HTTP 请求 RequestBody 只能被读取一次&#xff1a;HttpServletRequest 的输入流 (InputStream) 在被读取后会被关闭&#xff0c;导致后续无法再次读取。本文将介绍如何通过 请求包装类 (RequestWrapper) 来解决这个问题。问题背景 当我们需要在以下场景中多次读取 Reques…

(LeetCode 面试经典 150 题) 226. 翻转二叉树 (深度优先搜索dfs )

题目&#xff1a;226. 翻转二叉树 思路:深度优先搜索dfs&#xff0c;时间复杂度0(n)。 C版本&#xff1a; /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr)…

2025牛客暑期多校训练营3(FDJAEHB)

题目链接&#xff1a;牛客竞赛_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ F Flower 思路 可知当n<a时无论怎么操作她都会离开 n%(ab&#xff09;是指进行完若干轮之后剩下的不足ab个&#xff0c;如果是>a的话那么最后一轮必然不在a中&#xff0c;否则就…

【KO】 Android基础

以下是对这些 Android 相关问题的解答: 1. Activity 与 Fragment 之间常见的几种通信方式 接口回调:Fragment 定义接口,Activity 实现该接口,Fragment 通过接口实例调用方法传递数据 。 使用 Bundle:Fragment 可通过 setArguments(Bundle) 传数据给自身,Activity 可在创…

Gradle构建工具教程:由来与发展史(版本演进与未来优势)

一、Gradle简介Gradle是一个基于Apache Ant和Apache Maven概念的项目自动化构建开源工具&#xff0c;使用基于Groovy的领域特定语言&#xff08;DSL&#xff09;声明项目设置。相较于传统XML配置&#xff0c;这种DSL使构建脚本更简洁易读。Gradle支持Java、Groovy、Kotlin、Sca…

@Rancher简介部署使用 - Docker Compose

Rancher 安装和使用介绍 - Docker Compose 文章目录Rancher 安装和使用介绍 - Docker Compose1. Rancher 简介1.1 什么是 Rancher1.2 Rancher 核心功能1.3 Rancher 架构2. 安装前准备2.1 系统要求2.2 环境准备3. 使用 Docker Compose 安装 Rancher3.1 创建 Docker Compose 文件…

程序员接私活的一些平台和建议,千万要注意,别掉坑里!

关于程序员接私活&#xff0c;社会各界说法不一&#xff0c;如果你确实急用钱&#xff0c;价格又合适&#xff0c;那就去做。 不过&#xff0c;私活也没有那么好做&#xff0c;一般私活的性价比远比上班拿工资的低。但是作为一个额外的收益渠道&#xff0c;一部分生活窘迫的程序…

多轮问答与指代消解

目录引言一、LangChain是怎么实现的多轮问答1、记忆模块&#xff08;Memory&#xff09;管理对话历史‌2、对话链&#xff08;Conversational Chain&#xff09;架构‌3、智能体&#xff08;Agent&#xff09;决策机制‌4、上下文感知的Prompt工程‌5、RAG&#xff08;检索增强…

文件IO、文件IO与标准IO的区别

一、文件IO --->fd&#xff08;文件描述符&#xff09;打开文件open读、写文件read/write关闭文件close#include <sys/types.h>#include <sys/stat.h>#include<fcntl.h>文件描述符&#xff1a;操作系统中已打开文件的标识符。小的、非负的整形数据范围&am…

【模型剪枝2】不同剪枝方法实现对 yolov5n 剪枝测试及对比

目录 一、背景 二、剪枝 1. Network Slimming 1.0 代码准备 1.1 稀疏化训练 1.2 剪枝 1.3 微调 1.4 测试总结 2. Torch Pruning&#xff08;TP&#xff09; 2.1 MagnitudePruner 2.1.1 剪枝 2.1.2 retrain 2.1.3 测试总结 2.2 SlimmingPruner 2.2.1 定义重要性评…

AI入门学习--AI模型评测

一、AI模型评测目标传统质量主要关注功能、性能、安全、兼容性等。 AI模型评测在此基础上,引入了全新的、更复杂的评估维度: 1.性能/准确性:这是基础,在一系列复杂的评测基准上评价个性能指标。 2.安全性:模型是否可能被用于恶意目的?是否会生成有害、违法或有毒的内容?是否容…

nt!MmCreatePeb函数分析之peb中OSMajorVersion的由来

第一部分&#xff1a;NTSTATUS MmCreatePeb (IN PEPROCESS TargetProcess,IN PINITIAL_PEB InitialPeb,OUT PPEB *Base) {PPEB PebBase;PebBase->OSMajorVersion NtMajorVersion;PebBase->OSMinorVersion NtMinorVersion;PebBase->OSBuildNumber (USHORT)(NtBuildN…