Python 数据和 JSON 编程指南

最后更新: 12/29/2025
作者: C 源跟踪
  • JSON 与 Python 的核心类型完美对应,对象和数组分别表示为字典和列表,使得数据交换变得简单直接。
  • Python 的 json 模块提供了灵活的转储/加载函数,并提供了美观的打印、自定义编码器和稳定的键排序等选项。
  • 从文件和 API 中读取、写入和解析嵌套 JSON 依赖于相同的核心工具,并结合仔细的错误处理。
  • 除了基本的序列化之外,Python 中的 JSON 还支持格式化、验证以及与其他数据格式(如 CSV 和 XML)的集成。

Python JSON 数据教程

JSON 已悄然成为网络上数据的默认语言。 如果你用 Python 编程,你会发现它无处不在:API、配置文件、小型项目“数据库”、日志,甚至测试用例。理解 Python 的数据类型如何映射到 JSON,以及如何…… json 模块确实有效,它是一种能让很多日常任务变得简单的技能。

本指南从Python程序员的角度讲解JSON, 本文解释了什么是 JSON,它与 JavaScript 的关系,它可以表示哪些 Python 类型,以及如何使用 JSON 解析、生成、美化打印、验证和自定义 JSON。 json我们还将探讨实际应用案例,例如处理文件和 API,以及处理嵌套数据和特殊情况(例如错误或特殊值)的技巧。 NaN 以及无穷大。

什么是 JSON 以及它与 Python 数据的关系

JSON,即 JavaScript Object Notation(JavaScript 对象表示法)的缩写,是一种用于存储结构化数据的文本格式。 JSON 最初的语法借鉴自 JavaScript 的对象和数组。尽管源于 JavaScript,但 JSON 与语言无关,几乎所有现代语言都支持它,包括 Python,这使其成为在服务、客户端和服务器之间交换数据的理想选择。

从概念上讲,JSON 只使用两个复合构建块: JavaScript 对象 以及 JavaScript 排列对象的行为很像 Python 字典,数组的行为则很像 Python 列表。凭借这两种类型以及少量基本类型,JSON 可以描述复杂的嵌套数据结构。

JavaScript(以及 JSON)中的对象看起来像这样: {"key1": value1, "key2": value2}它是一个键值对集合,其中键是字符串,值可以是任何有效的 JSON 值(包括其他对象或数组)。这与 Python 的类似。 dict.

JavaScript(以及 JSON)中的数组类似于 Python 列表: 它是一个有序的值集合,同样可以使用任何有效的 JSON 类型。对象和数组可以任意嵌套,从而对用户个人资料、配置树或 API 响应等丰富数据进行建模。

JSON 类型和 Python 类型之间的映射关系非常简单直接。 这就是为什么你有时会听到人们开玩笑地称它为“PYON”(Python对象表示法)。当Python对JSON进行编码或解码时,遵循以下对应关系:

  • JSON 对象 → Python dict
  • JSON 数组 → Python list
  • JSON 字符串 → Python str
  • JSON 数字(整数)→ Python int
  • JSON 数字(实数)→ Python float
  • JSON true Python True
  • JSON false Python False
  • JSON null Python None

一个重要的限制是,JSON 对象键始终是字符串。 所以如果你用 Python 编码 dict 对于非字符串类型的键(例如整数或元组),这些键将被强制转换为字符串,或者根据您的设置引发错误。JSON 非常适合持久化结构化数据,例如配置或记录,但它也存在一些问题。 不会 一种适用于任意 Python 对象的通用序列化机制。

Python JSON 数据映射

Python 内置的 json 模块

Python 自带一个名为“Python”的标准库模块。 json, 它提供了处理 JSON 所需的一切:解析字符串、从文件加载数据、序列化 Python 对象,以及自定义数据的编码和解码方式。对于典型的 JSON 任务,您无需任何外部依赖。

您最常使用的四个核心功能是: json.dumps()json.dump() 用于将 Python 对象转换为 JSON,以及 json.loads()json.load() 用于将 JSON 转换回 Python 类型。带“s”的版本用于字符串,不带“s”的版本用于类文件对象。

这个 json 编码器默认支持一组特定的Python类型, 亦即 dict, list, tuple (以数组形式) str,数字(int, float,以及整数/浮点数派生枚举),以及三个特殊的单例 True, FalseNone. 根据前面描述的映射关系,这些值将转换为对应的 JSON 值。

如果您需要序列化自定义对象或数据类型, 该模块的设计具有可扩展性:您可以对 JSON 编码器进行子类化并实现以下功能: default() 或者传递自定义方法。 default 功能进入 json.dump() / json.dumps()该自定义钩子应该返回可序列化为 JSON 的数据(例如……)。 dict or list),或提高 TypeError 如果它不知道如何处理给定的对象。

该模块底层还提供了诸如以下的方法: encode()iterencode(), 它将 Python 数据转换为 JSON 字符串, iterencode() 逐步生成编码后的数据块。这些方法虽然不常直接使用,但如果您需要流式传输非常大的 JSON 响应,则值得了解。

将 Python 对象转换为 JSON

当您想将 Python 数据转换为 JSON 文本时,您可以使用 json.dump() or json.dumps(), 这取决于您是想直接写入文件还是在内存中获取 JSON 字符串。这两个函数共享相同的核心参数,这些参数允许您控制转换行为。

该功能 json.dump(obj, fp, ...) 接受一个Python对象和一个类文件对象, 并写入 JSON 表示形式 obj 到该文件。其内存中的对应文件, json.dumps(obj, ...)返回 JSON 字符串而不是写入文件。它们都接受一系列关键字参数,例如: skipkeys, ensure_ascii, check_circular, allow_nan, indent, separators, defaultsort_keys.

这些选项中的每一个都会对编码行为进行微调,而这些微调在实际项目中都非常重要: 您可以选择是否跳过无效键、强制 ASCII 输出、美化打印结果、控制空格、为非标准对象定义自定义序列化,或者稳定键顺序以进行测试和差异比较。

以下是主要参数的实际含义:

  • skipkeys: 如果设置为 True字典键不是类型 str, int, float, bool or None 被默默跳过,而不是被提升。 TypeError如果您希望在密钥异常时快速失败,请保留此设置。 False.
  • ensure_ascii: ,尤其是 True (默认情况下),非 ASCII 字符和不可打印字符会被转义(例如,使用转义字符)。 \uXXXX因此,输出结果仍然是纯 ASCII 码。 FalseUnicode 字符按原样写入,这通常更适合人类可读的配置或日志。
  • check_circular: if True编码器会检查列表、字典和自定义编码对象中的循环引用,以防止无限递归。将其设置为 False 这会削弱安全网,并可能导致…… RecursionError 如果你的结构是自指的。
  • allow_nan: if True特殊的浮点值,例如 NaN, Infinity-Infinity 即使它们并非规范中严格意义上有效的 JSON,也允许以 JavaScript 兼容的方式进行编码。 False尝试对这些值进行编码会引发异常。 ValueError.
  • indent: 一个非负整数(或字符串),用于控制格式化输出。正数表示每层嵌套的空格数。字符串(例如) "\t") 直接用于缩进。 None (默认)选择最紧凑的表示形式,除了必要的换行符之外,不会添加额外的换行符。
  • separators: 元组 (item_separator, key_separator) 控制项目之间以及键值对之间的标点符号和空格。为了获得最简洁的 JSON,通常使用 (",", ":") 删除所有可选空格。
  • default: 一个接收编码器无法处理的任何对象的函数。它必须返回一个可序列化的替换对象(例如一个 JSON 对象)。 dict or list),或提高 TypeError这是使你的类可序列化的主要钩子。
  • sort_keys: if True字典的编码方式是键已排序。这对于回归测试和可复现输出非常有用,因为您需要确保 JSON 转储在不同运行中保持一致。

举个具体的例子,假设你有一个混合 Python 列表 包含整数和一个字典,字典中包含名称、ID 和浮点分数。您可以像这样创建和存储 JSON:

import pathlib
import json

path = pathlib.Path("myTextFile.json")
data =

with path.open(mode="wt") as f:
    json.dump(data, f)

print(json.dumps(data, indent=4))

由于以下原因,打印出的 JSON 格式会很好: indent=4, 将每个列表项和字典键显示在单独的行上。与单行密集文本相比,这使得调试和手动编辑更加容易。

将 JSON 解析回 Python

将 JSON 文本转换回 Python 对象, 您可以使用匹配的函数对: json.load() (对于类文件对象) json.loads() (针对 JSON 字符串)。这些函数解析输入,并根据与之前相同的映射表重新创建 Python 类型。

签名大致如下: json.load(fp, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, kw)json.loads(s, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, kw)从最基本的层面来说,你只需要 JSON 输入就可以调用它们,但额外的参数可以实现更高级的解析行为。

钩子 object_hookobject_pairs_hook 允许您自定义如何将 JSON 对象转换为 Python 结构, 通过向你提供解码后的信息 dict 或一份清单 (key, value) 分别对应不同的键值对。如果您想直接从 JSON 构建自定义类或以特定方式保留顺序,这将非常有用。

其他可调用对象,例如 parse_float, parse_intparse_constant 允许您控制数字和特殊标记的解释方式。例如,您可能希望使用 Decimal 而不是 float 以货币价值衡量,或进行转换 "NaN", "inf""-inf" 变成你选择的哨兵物品。

沿用前面的例子,你可以像这样读取你编写的JSON文件:

with path.open(mode="rt") as f:
    data = json.load(f)
print(data)

最终输出结果将是一个标准的Python列表和字典。 例如 你可以使用所有常见的 Python 操作来处理它。从你的代码角度来看,它仍然只是“数据”。

Python 可以将哪些数据类型转换为 JSON

并非所有Python对象都能直接转换为JSON, 因此,记住允许的集合很有帮助。实用编码器支持常见的容器和标量类型,以及布尔值和整数。 None并将它们映射到最小的 JSON 类型集。

默认情况下,您可以安全地将以下 Python 对象传递进去。 json.dumps():

  • dict (编码为 JSON 对象)
  • listtuple (编码为 JSON 数组)
  • str (编码为 JSON 字符串)
  • intfloat (以 JSON 数字形式编码)
  • TrueFalse (编码为 truefalse)
  • None (编码为 null)

当Python对这些数据进行编码时,将其映射回JSON就非常简单了。 解码时则相反。例如,Python tuple 变成 JSON 数组,然后你得到一个 list 重新加载。枚举派生自 int or float 也可以用数字编码。

其他所有东西都需要定制。 default 处理器 (将对象转换为可序列化的表示形式)或将导致 TypeError这是有意为之:JSON 旨在用于数据,而不是用于像您可能使用序列化方式那样,用于具有行为和方法的任意对象图。 pickle.

对于大多数日常工作而言,这部分类型涵盖了绝大多数的使用场景。 包括 API 有效负载、配置树、用户偏好、基本日志以及用于原型或单用户工具的小型“类似数据库”的文件。

精美打印、紧凑输出和有序按键

原始JSON输出通常完全有效,但难以阅读。 因为它通常生成时不会包含不必要的空格。为了进行调试、记录日志或与其他开发人员共享,您通常需要的是易读且缩进良好的 JSON,而不是一行代码。

这个 indent 的参数 json.dumps() 是实现精美打印的主要手段。 允许你告诉 Python 每个缩进级别使用多少个空格(或哪个字符串)。一个典型的选择是 indent=4虽然有些代码库更喜欢使用两个空格或制表符;不同项目的风格约定各不相同。

这个 separators 参数设置允许你进一步微调空格, 给出一个类似这样的元组 (", ", ": ") 默认情况下,输出结果对人类友好。如果您想要尽可能紧凑的表示形式(例如,为了减少网络传输的有效载荷大小),您可以进行设置。 separators=(",", ":") 删除逗号和冒号后的空格。

当您需要确定性输出时,例如在单元测试或快照比较中, 激活 sort_keys=True 编码器会按排序顺序输出字典键。这样,即使两次运行生成了语义相同的数据,也不会因为字典输出键的顺序不同而导致结果差异。

一起, indent, separatorssort_keys 赋予你很大的控制权 你的 JSON 是否针对机器进行了优化(紧凑、无空格),还是针对人类进行了优化(缩进、对齐、在多次运行中保持稳定形状)。

嵌套数据、解析策略和访问模式

在实际的 JSON 中,扁平结构是例外; 你通常会处理嵌套对象和数组。想想电子商务应用程序中典型的用户记录:个人信息、嵌套的收货地址、嵌套的账单信息,可能还有订单列表,每一项本身都是复杂的结构。

将JSON解码成Python时,嵌套数据会变成字典和列表的组合。 您可以使用标准索引和键查找来访问它。对于浅层结构,这很简单: data, data,等等。

对于嵌套较深或动态的结构,您可能更倾向于采用更通用的方法。 例如,编写一个小型递归函数来搜索键,或者遍历字典和列表组成的树。在遍历任意嵌套的数据时,递归解决方案通常比迭代解决方案更简洁、更易读。

非嵌套(扁平)JSON更容易通过硬编码键直接访问, 对于小型实用程序或完全控制输入的情况来说,这完全没问题。但是,在使用外部 API 时,通常会编写一些小型辅助函数来封装数据结构,这样就不会造成数据混乱。 代码库中到处都是链式调用。

无论深度如何,相同 json.loads() 行为准则适用: 该函数接受一个 JSON 字符串,并生成原生 Python 类型,然后您可以使用常规的 Python 工具对其进行操作。除了常规语法外,无需任何特殊语法。 dictlist 索引。

使用 JSON 文件:读取、写入和追加

JSON 是一种出人意料地方便的轻量级存储格式。 对于小型项目、配置文件或需要保持一些持久状态的脚本,通常只需一两个 JSON 文件即可满足需求,而无需直接使用完整的数据库。

将 JSON 写入文件通常是一个两步过程: 使用以下方式序列化 Python 数据 json.dumps() 或直接 json.dump()然后确保将生成的字符串写入磁盘。如果您调用 open('data.json', 'w'),您将获得一个写入模式下的文件句柄,该句柄要么创建文件,要么在文件已存在时将其截断。

对于嵌套结构,其协议与平面数据并无不同: 你仍然使用相同的 json.dump() 调用时,嵌套的列表和字典组合会递归编码。通常你只需要决定在可读性和文件大小之间权衡缩进量即可。

从文件中读取JSON的过程则相反:以文本模式打开文件, 将文件对象传递给 json.load()这样就能得到你的 Python 数据结构。同样,这种行为与嵌套深度无关——解码器会为你处理所有这些问题。

如果您需要将 JSON 数据追加到现有文件中, 情况变得更加复杂。JSON 本身并不支持简单的“流式追加”,因为整个文件必须是有效的 JSON。一种常见的做法是存储一个记录数组,然后读取、修改或写入整个数组;或者使用换行符分隔的 JSON,其中每一行都是一个独立的 JSON 对象,您可以向其中追加数据而不会覆盖前面的行。

JSON 在现实世界中的应用:API、存储和交换

一旦开始构建真正的应用程序,JSON 很快就会成为粘合剂。 它连接Web客户端和服务器、微服务和第三方API。它的价值在于其简洁性,以及人类仍然能够相对轻松地阅读和编辑它。

在API交互中,JSON是迄今为止最常见的有效负载格式。 尤其是在 RESTful 服务中。Python 应用程序通常会使用诸如此类的库。 requests 发送HTTP请求和 接收 JSON 响应然后解析这些响应 json.loads() 或者使用对其进行封装的辅助方法。

JSON也是配置文件和日志的常用格式。 JSON 的结构化键值特性使其比纯文本更具表现力,同时又比完整的数据库简单得多。系统组件可以通过 JSON 共享配置,日志聚合器可以解析 JSON 日志,从而更轻松地进行过滤或分析。

另一个重要的应用场景是数据结构的序列化和反序列化。 将内存中的集合转换为 JSON 字符串(序列化),然后再将其重构(反序列化)。这就是存储用户偏好设置的方式。 传输结构化消息 通过队列,或跨服务边界发送嵌套对象,前提是您坚持使用 JSON 兼容的类型或提供自定义编码器。

除了JSON格式之外,Python代码还经常需要在JSON和其他格式之间进行转换。 例如 XML、CSV 或纯文本。举例来说,您可以从旧系统中读取 CSV 文件,将其转换为字典列表,然后以 JSON 格式导出到现代 API。或者,您可以从 API 获取 JSON 数据,对其进行规范化,然后将其转换为 CSV 格式,供分析师导入到电子表格中。

JSON 的格式化、验证和其他操作

一旦你掌握了基本的读写能力, 您可以对 JSON 数据执行许多虽小但有用的操作来改进您的工作流程:格式化以提高可读性、扁平化嵌套结构、验证字符串是否真的是 JSON 以及对数据进行排序以进行一致的比较。

美化打印 json.dumps(..., indent=...) 这是第一步, 它提供了清晰的层级结构,让您能够一眼发现结构问题。这在调试或在文档中分享示例时尤其有用。

扁平化嵌套的JSON可以简化下游处理和分析。 尤其是在需要将数据转换为 CSV 等表格形式,或将其导入需要键值对而非深度嵌套对象的工具时,扁平化操作尤为重要。通常情况下,您需要使用递归或迭代遍历字典和列表来实现数据扁平化。

验证JSON通常归结为尝试解析它并捕获异常, 尤其是在你只是想验证字符串的语法正确性时。对于更严格的检查,你可以使用 JSON Schema 和外部库,但在许多情况下,简单的验证就足够了。 try/except 围绕 json.loads() 足够。

按特定值或键对JSON数据进行排序有助于比较响应结果。 生成用于测试的稳定快照,或者仅仅是确保相似的对象分组在一起。你可以在转储之前对底层 Python 列表和字典进行排序,或者依赖于…… sort_keys=True 当重点放在对象内部的关键顺序上时。

处理 JSON 时的错误

即使是结构良好的系统也可能遇到格式错误的 JSON 或意外数据。 因此,对 JSON 解析和编码进行稳健的错误处理至关重要。Python 通过异常来表达这些问题,而处理它们的惯用方法是将操作包装在 `__init__` 语句中。 try...except 块。

解码JSON时,最常见的问题是语法无效。 例如,房产名称缺少引号或末尾多加逗号。 json 模块将引发解码错误(通常 json.JSONDecodeError您可以捕获并记录这些消息,或者将其转换为用户友好的消息。

例如,尝试解析一个损坏的字符串可能会导致如下错误: Failed to decode JSON: Expecting property name enclosed in double quotes: line 1 column 29 (char 28)这种消息不仅告诉你解析失败了,还告诉你解析器在输入中的哪个部分出了问题。

在编码方面,你可能会遇到 TypeError 尝试序列化不支持的类型时, or ValueError 如果你不允许 NaN 以及通过无穷大 allow_nan=False 但您的数据包含此类值。容器中的循环引用也可能触发此操作。 RecursionError 如果禁用循环检查。

最佳实践是将JSON操作视为易出错的I/O操作。 尤其是在从网络源或外部文件读取数据时:始终假设可能会出现问题,并相应地捕获异常,必要时添加验证层以对数据强制执行更具体的约束。 json.loads() 或者 API 辅助方法 try...except 代码块可以保护其余代码免受级联错误的影响,并允许您返回错误。 用户友好的 JSON 错误 在适当的时候向客户提供服务。

在 Python 中使用 JSON 和 Web API

大多数你用Python调用的Web API都会发送和接收JSON数据。 典型的开发技术栈结合了 requests (用于 HTTP 的)库 json 该模块(用于解析和生成 JSON)使 API 集成感觉非常自然。

一种常见的模式是调用 API 端点, 检查响应状态码是否表示成功,然后 解析 JSON 正文由此,您可以访问字段、处理嵌套数据,并将响应映射到您自己的领域模型或视图对象。

当涉及网络调用时,错误处理就显得尤为重要。 因为你不仅会遇到无效的 JSON,还会遇到超时、连接错误或服务器端故障,导致服务器返回 HTML 而不是 JSON。封装 json.loads() 或者 API 辅助方法 try...except 代码块可以保护其余代码免受级联故障的影响。

解析完成后,API JSON 的行为就和其他 Python 数据结构一样了。 因此,前面讨论的所有技巧——格式化输出、数据扁平化、数据验证、排序——都可以直接应用。熟练地在 Python 数据和 JSON 之间切换,对于连接各种服务来说,能够极大地提高工作效率。如果您专注于…… 构建实际应用及早关注 JSON 处理模式可以节省以后的调试时间。

Python 中的 JSON 与其说是一个单一的函数调用,不如说是一个工具箱: 清晰的类型映射、灵活的编码参数、自定义类型的钩子、简单而强大的文件 I/O 以及用于解析、格式化和验证来自外部世界的数据的强大模式,所有这些都使 JSON 成为处理现代数据驱动应用程序的 Python 程序员的天然选择。

相关文章:
解决:获取网页数据为json python
相关文章: