你是否正在寻找使用 Python 解析 JSON 的方法?那么你来对地方了!本文将讨论关于 Python 中 JSON 支持的所有内容,包括解析、生成、创建以及常见错误的应对方法。

作为一名网页开发者甚至是应用开发者,你无法避开 JSON,因为它是用于在 Web 服务器之间传输数据的格式。JSON 是 JavaScript 对象表示法(JavaScript Object Notation)的缩写,这让它看起来像是依赖于 JavaScript 的格式。

然而,尽管 JSON 源自 JavaScript,但它实际上是与 JavaScript 无关的语言,并被广泛应用于所有编程语言中,如 Python、Java、C#、PHP 等等。本文的重点是 Python 编程,我将向你展示如何使用 Python 解析 JSON,并进一步介绍如何处理和创建 JSON 文件。那么,首先,什么是 JSON?


什么是 JSON?

JSON是一种基于文本的数据格式,用于使用 Javascript 对象语法表示结构化数据。本质上,它只是基于文本的,在 Python 中,您会将其称为用于存储结构化数据的字符串。虽然 JSON 看起来像 JSON 对象,因为它们共享相同的语法,但它也看起来像 Python 中的字典,并且可以转换为字典。

它确实有多种用途,例如数据传输、用作配置文件、显示公共数据、数据迁移、以 JSON Web 令牌形式进行 Web 授权等等。它因其易于理解的语法、轻量级特性、独立于语言且非常灵活而受到许多人的青睐。虽然 JSON 可以用作脚本中的变量,但它也有自己的文件格式,以 .json 结尾,而其 MIME 类型为 application/JSON。


JSON 解码和编码的工作原理

JSON 最常见的用例是跨网络或服务器传输数据。在大多数情况下,两端的设备无法理解彼此的数据格式。因此,为了实现兼容性,原生对象中的结构化数据会通过称为序列化的过程转换为 JSON,或编码为字符串。

另一端的接收服务器需要将其转换为自己的原生对象,这可以通过反序列化来完成。通过反序列化,编程语言能够将 JSON 数据转换为自己的原生对象。

举例来说,一个用 Kotlin 编写的移动应用程序将创建并发送 JSON(显然是序列化的),当您在 Python Web 应用程序中收到它时,您会将其反序列化为 Python 字典对象。每种流行的编程语言都有序列化和反序列化 JSON 结构化数据的方法,包括 Python。

有了对此的支持,不同的服务器可以基于不同的编程语言,但能够有效且高效地进行通信,因为它们在通信中使用的数据格式双方都可以理解。


在 Python 中解析 JSON 数据

如前所述,所有编程语言都有序列化和反序列化 JSON 数据的方法,Python 也不例外。对于 Python,JSON 模块是标准库的一部分,因此您无需单独安装它。您所要做的就是导入并使用它。在此模块中,有两种用于解析 JSON 的方法。

这包括用于从字符串解析 JSON 的 json.loads 和用于从文件解析 JSON 的 json.load。

除了解析之外,您还需要为想要发送的任何数据生成 JSON,这是通过使用 json.dumps 将 Python 字典序列化为 JSON 来完成的。


Python 解析JSON 字符串   

要在 Python 中解析 JSON 字符串,您需要先加载它,将其从 JSON 字符串转换为 Python 字典。转换后,您现在可以开始解析和提取数据中感兴趣的特定数据点。让我们看下面的一个例子。

import json

user_json = '{"name": "Jasper Sparrow", "age": 46, "country": "US"}'

user_data = json.loads(user_json)

print(user_data)

print(type(user_data))

print(user_data['age'])

如您所见,我首先导入 JSON 模块。 user_json 变量包含一个 JSON 字符串。仔细检查,您会发现它看起来像一个字典,但括在单引号 (‘ ‘) 中。如果您实际使用 type(object) 方法检查其类型,则响应将是一个类型字符串。

使用 json.loads 方法,将其转换为字典。您将在带有 type(user_data) 的 print 语句中看到这一点。由于它现在是字典,因此您可以将名称、年龄和国家/地区作为字典的键来访问。这样做的一个好处是它保留了数据类型。例如,年龄仍然是一个整数,因为 JSON 中最初定义的年龄是一个整数。


Python从文件加载 JSON

在上面的代码中,我们从字符串中获取 JSON 数据,这是 Web 应用程序接收来自客户端的请求的典型情况。但是,JSON 不仅以这种方式提供。在其他情况下,您将数据保存在 .json 文件中。一个常见的例子是配置和迁移文件。在这种情况下你如何处理它?你使用 json.load 方法而不是 json.loads 方法。

为此,您首先需要打开文件并将其内容加载到 load 方法中,然后再进行解析。下面是如何完成此操作的示例。在包含脚本的同一文件夹中,创建一个名为 user_infor.json 的文件并在其中添加以下内容。

{

    "name": "Jasper Sparrow",

    "age": 46, "country": "US"

}

Now to the main code below.

import json

with open('user_info.json', 'r') as file:

    data = json.load(file)

print(data)

print(data['country'])

解析过程与上面第一个代码中的方法相同。一旦将其转换为字典,就可以使用字典的键来访问数据。


Python 中 JSON 转换为字典的一般规则

要将 JSON 字符串/文件转换为 Python 字典,您需要遵守一些规则。下面让我们看看其中的一些规则。

仅可解析有效的 JSON:

将 JSON 字符串转换为 Python 字典时,首要规则是它必须是有效的 JSON。如果出现某些错误(例如未在正确位置使用冒号),则无法转换,因为 Python 会引发异常。

对于正确的来源使用正确的方法:

从上文中可以看出,为了便于解析,JSON 数据基本上有两种来源。第一种是字符串,第二种是文件。如果要从字符串获取 JSON,请确保使用 json.loads 方法;如果要从文件获取 JSON,请确保使用 json.load 方法。

注意性能问题:

加载 JSON 的方法的时间复杂度为 O(n)。这意味着加载较大的文件需要更多时间。当解析较大的文件时,这可能会成为一个问题。如果您开始注意到性能问题,则应使用比标准库中的 JSON 模块更快的替代库。我稍后将讨论一些替代方案。

处理异常:

在大多数情况下,您要处理的 JSON 是由其他客户端或服务器发送的,因此您无法控制它。这意味着您无法判断它们是否结构正确。如果不是,则会引发异常,您需要处理异常以避免意外行为。


在 Python 中生成 JSON

在上一节中,我们将 JSON 字符串和文件加载并解析为 Python 字典。在本节中,我将向您展示如何使用 JSON 模块中的方法将字典转换为 JSON,从而生成 JSON 字符串和文件。这样,您也可以发送 JSON 响应。


生成 JSON 字符串

要将字典转换为 JSON 字符串,你只需将字典作为参数传递给 json.loads,如下所示

import json

user_info = {

    "name": "Jasper Sparrow",

    "age": 46, "country": "US"

}

user_json = json.dumps(user_info)

print(type(user_json))

从代码中,你可以看到 user_info 是一个包含用户姓名、年龄和国家/地区的字典。user_json 保存转换后的数据。如果你运行上面的代码,它会显示 type string 而不是 type dict,因为它已被转换为字符串。就是这么简单。你也可以通过加载相同的数据来玩一玩。


生成 JSON 文件

要生成带有 .json 扩展名的 JSON 文件,您可以打开具有写入权限的文件并在其中写入 JSON。不用担心,如果文件不存在,它会为您创建一个。查看如何使用相同的数据点完成此操作。

import json

user_info = {

    "name": "Jasper Sparrow",

    "age": 46, "country": "US"

}

with open('user_info.json', 'w') as file:

    json.dump(user_info, file)

如果您运行上述代码,您会注意到一个新文件已添加到脚本所在的文件夹中。这将是 user_info.json 文件,并将包含转储到其中的 user_info 数据。


如何解析大型 JSON 数据

标准库中的 JSON 模块为您提供了一种简单而有效的 JSON 数据解码和编码方法。但是,当面对大型 JSON 数据集或某些高吞吐量应用程序时,它不是一个高效的库。

如前所述,这是因为它的时间复杂度为 O(n),随着数据集的增加,解析所需的时间也会增加。当您必须解析大型 JSON 字符串或文件时,您会注意到它需要时间,这可能会开始导致性能问题。

不幸的是,就时间复杂度而言,没有更好的选择,因为所有替代方案都是 O(n)。但是,它们的实现不同,这使得其中一个比其他的快得多。作为替代方案,如果您开始面临 Python 中标准 JSON 模块的性能开销,则应该使用 ujson、rapidjson 或 orjson。

它们比标准 JSON 模块快得多。为了获得最佳结果,您需要对这 3 个模块进行基准测试并选择最快的模块,这实际上取决于您正在解析的 JSON。


解析 JSON 时遇到的常见错误

您必须始终遵循的一条经验法则是,在处理外部数据时,永远不要相信并期望一切都会顺利,JSON 也不例外。您需要为异常做好计划并处理它们,这样您的代码就不会意外停止。以下是您应该尝试捕获和处理的一些主要异常。


JSON解码错误

常见的错误是 JSONDecodeError。当 JSON 数据由于编码错误而无效时,就会发生此错误。这可能是由于忘记关闭花括号、缺少逗号、括号不匹配、添加不需要的额外字符或其他类型的语法错误造成的。简而言之,当您将格式错误的 JSON 数据提供给解码器时,就会出现此错误。让我们看下面的一个例子。

import json

invalid_json = '{"name": "Alice", "age: 25}'  # Missing closing quote

try:

    data = json.loads(invalid_json)

except json.JSONDecodeError as e:

    print("Invalid JSON:", e)

如上所示,导致错误的原因是 age 缺少一个右引号。引发的异常是 JSONDecodeError。然而,在代码中,这个异常已被捕获并处理。这是一个你必须始终处理的异常,因为外部数据不能被信任为有效且无畸形。


键错误

解析 JSON 字符串/文件时会遇到的另一种错误类型是 KeyError。然而,这更多的是与 Python 字典相关的问题,而不是解析本身的问题。当你无法将 JSON 解码为字典时,你会得到 JSONDecodeError。

但是,当您能够将其转换为字典,但由于使用了错误的键而无法解析所需的数据时,您将得到 KeyError。下面是一个例子。

import json

valid_json = '{"name": "Bob", "age": 30}'

data = json.loads(valid_json)

try:

    print(data["gender"])  # Key "gender" doesn't exist

except KeyError as e:

    print("Key not found:", e)

从代码中,你可以看到我试图访问实际上不存在的性别键。在代码中,我只是在控制台上打印了错误。处理此问题的更好方法是使用 dict.get(key, default_value) 方法而不是使用 dict[key] 来提供默认值。如果不存在键,dict.get 不会引发异常。


类型错误

当您尝试对非预期类型的​​值执行操作(例如使用可变为访问键的列表)时,会发生 TypeError。当您尝试使用其他数据类型访问值时(例如以整数形式访问字符串格式的数值),也会引发此错误。让我们看一个 TypeError 的示例以及如何处理它。

import json

valid_json = '{"name": "Charlie", "age": "35"}'  # Age is a string

data = json.loads(valid_json)

try:

    age = data["age"] + 10  # Trying to add an integer to a string

except TypeError as e:

    print("Type mismatch:", e)

在此示例中,您会看到原始 JSON 字符串中的年龄值属于字符串类型。但是,在尝试将用户的年龄增加 10 岁时,我们使用了整数加法运算符。这里应该做的是先将字符串中的年龄转换为整数,然后再向其添加新值。

如果你实际运行上面的代码,你会注意到它打印了顶部不匹配和字符串上的错误。如你所见,我们只打印了错误,并没有采取任何措施。但是,如果不捕获它,代码将抛出异常。


IOError

处理 JSON 文件时遇到的常见错误列表中的最后一个是 IOError。这只会发生在访问或写入文件时,而不会发生在字符串中。这是在读取或写入文件时出现问题时引发的错误类型。

发生这种情况的原因有很多。其中一些原因包括没有权限读取或写入文件、现有文件或无法访问文件。以下是此类示例。

import json

try:

    with open('nonexistent_file.json', 'r') as f:

        data = json.load(f)

except IOError as e:

    print("Error reading file:", e)

如您所见,我试图读取一个不存在的文件。但是,由于我遇到了异常,代码不会崩溃。但您可以看到,除了将其打印在屏幕上之外,没有实际的处理方法。


结    论

Python 让处理 JSON 文件和字符串变得非常简单。无论是解码还是编码 JSON,你都可以通过几行代码轻松完成。

虽然标准库中的 JSON 模块在这方面表现良好,但在处理大型文件或字符串时,它并不是最佳选择,因为解析或编码大型文件可能会耗费较长时间。当你遇到这种情况时,最好使用本文性能部分中提到的替代方案。

这篇文章有用吗?

点击星号为它评分!

平均评分 / 5. 投票数:

到目前为止还没有投票!成为第一位评论此文章。

No more articles