自学内容网 自学内容网

Python内置模块-Json:轻松处理数据交换的艺术

目录

一、Json模块简介

二、Json模块的核心功能

三、Json模块的主要函数和类

四、Json模块的高级应用

自定义序列化

自定义反序列化

处理循环引用

总结


在Python的编程世界中,Json模块以其简洁、高效的特点,成为了处理JSON数据不可或缺的利器。JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,它基于键值对的方式组织数据,支持嵌套结构,包括对象和数组,因此非常适合在网络传输和存储中使用。

Python内置的Json模块提供了丰富的功能,能够方便地将Python对象序列化为JSON字符串,以及将JSON字符串反序列化为Python对象。本文将为新手朋友们详细介绍Json模块的使用方法和技巧,通过丰富的代码示例和案例,帮助大家轻松掌握Json模块的应用。

一、Json模块简介

Json模块是Python标准库的一部分,它提供了一系列函数和类,用于处理JSON数据。这些函数和类能够方便地将Python对象(如字典、列表等)转换为JSON格式的字符串,以及将JSON格式的字符串解析为Python对象。Json模块的使用非常简单,只需要导入模块后,调用相应的函数即可完成数据的序列化和反序列化操作。

二、Json模块的核心功能

Json模块的核心功能主要包括以下几个方面:

  • 序列化:将Python对象转换为JSON格式的字符串。Json模块提供了json.dumps()函数和json.dump()函数来实现这一功能。json.dumps()函数是在内存中操作,将Python对象转换为JSON字符串;而json.dump()函数则是将Python对象序列化后写入到文件中。
  • 反序列化:将JSON格式的字符串解析为Python对象。Json模块提供了json.loads()函数和json.load()函数来实现这一功能。json.loads()函数是在内存中操作,将JSON字符串解析为Python对象;而json.load()函数则是从文件中读取JSON数据并解析为Python对象。
  • 处理复杂数据类型:除了基本的字典和列表之外,JSON还支持一些其他的数据类型,如字符串、数字、布尔值、null(在Python中表示为None)等。但是,JSON不支持Python中的元组、集合或自定义类等复杂类型。如果需要处理这些类型,可以在使用json.dumps()或json.dump()之前将它们转换为列表或字典,并在使用json.loads()或json.load()之后进行转换。
  • 自定义序列化和反序列化:Json模块还提供了自定义序列化和反序列化的功能。通过default参数和object_hook参数,可以实现自定义类的序列化和反序列化,使得Json模块更加灵活,可以适应各种数据结构。

三、Json模块的主要函数和类

Json模块包含多个函数和类,以下是一些常用的函数和类的详细介绍:

json.dumps(obj, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, kw)

该函数将Python对象序列化为JSON格式的字符串。

其中,obj是要序列化的Python对象;indent参数用于指定缩进空格数,可以美化输出的JSON字符串;separators参数用于指定分隔符,可以自定义键值对之间的分隔符和项之间的分隔符;default参数用于指定自定义序列化函数,用于处理无法直接序列化的对象;sort_keys参数用于指定是否对字典的键进行排序。

import json  
  
data = {"name": "John", "age": 30, "city": "New York"}  
json_string = json.dumps(data, indent=4)  
print(json_string)

输出:

{  
    "name": "John",  
    "age": 30,  
    "city": "New York"  
}

json.dump(obj, fp, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, kw)

该函数将Python对象序列化为JSON格式并写入文件中。其中,obj是要序列化的Python对象;fp是一个文件对象,用于写入序列化后的JSON数据;其他参数与json.dumps()函数相同。

import json  
  
data = {"name": "Alice", "age": 25, "city": "London"}  
with open("data.json", "w") as file:  
    json.dump(data, file, indent=4)

这样,data字典就会被序列化为JSON格式,并写入到data.json文件中。

json.loads(s, *, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, kw)

该函数将JSON格式的字符串解析为Python对象。其中,s是要解析的JSON字符串;object_hook参数用于指定自定义反序列化函数,用于处理无法直接反序列化的对象。

import json  
  
json_string = '{"name": "John", "age": 30, "city": "New York"}'  
data = json.loads(json_string)  
print(data)

输出:
{'name': 'John', 'age': 30, 'city': 'New York'}

json.load(fp, *, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, kw)

该函数从文件中读取JSON数据并解析为Python对象。其中,fp是一个文件对象,用于读取JSON数据;其他参数与json.loads()函数相同。

import json  
  
with open("data.json", "r") as file:  
    data = json.load(file)  
print(data)

这样,data.json文件中的JSON数据就会被解析为Python对象,并存储在data变量中。

JSONDecodeError

这是一个异常类,当解析JSON字符串时发生错误时,会抛出此异常。可以通过捕获此异常来处理解析错误。

import json  
  
json_string = '{"name": "John", "age": 30, "city": "New York",}'  # 注意这里多了一个逗号,是无效的JSON字符串  
try:  
    data = json.loads(json_string)  
except json.JSONDecodeError as e:  
    print(f"Error decoding JSON: {e}")

输出:

Error decoding JSON: Expecting value: line 1 column 41 (char 40)

四、Json模块的高级应用

除了上述基本功能外,Json模块还支持一些高级应用,如自定义序列化和反序列化、处理异常等。以下是一些高级应用的示例:

自定义序列化

如果有一个自定义的类,需要将其实例序列化为JSON字符串,可以通过实现自定义序列化函数来实现。

import json  
  
class Person:  
    def __init__(self, name, age):  
        self.name = name  
        self.age = age  
  
    def to_json(self):  
        return {"name": self.name, "age": self.age}  
  
def person_encoder(obj):  
    if isinstance(obj, Person):  
        return obj.to_json()  
    raise TypeError("Object of type 'Person' is not JSON serializable")  
  
person = Person("Emma", 28)  
json_string = json.dumps(person, default=person_encoder, indent=4)  
print(json_string)

输出:

{  
    "name": "Emma",  
    "age": 28  
}

在这个例子中,我们定义了一个Person类,并实现了一个to_json()方法,用于将Person实例转换为字典。

然后,我们定义了一个person_encoder()函数,该函数检查对象是否为Person类的实例,如果是,则调用to_json()方法将其转换为字典;否则,抛出TypeError异常。最后,我们使用json.dumps()函数将Person实例序列化为JSON字符串,并指定default参数为person_encoder()函数。

自定义反序列化

同样地,如果有一个自定义的类,需要将其从JSON字符串中反序列化为实例,可以通过实现自定义反序列化函数来实现。

import json  
  
class Person:  
    def __init__(self, name, age):  
        self.name = name  
        self.age = age  
  
def person_decoder(obj):  
    if "name" in obj and "age" in obj:  
        return Person(name=obj["name"], age=obj["age"])  
    return obj  
  
json_string = '{"name": "Emma", "age": 28}'  
person = json.loads(json_string, object_hook=person_decoder)  
print(person.__dict__)

输出:

{'name': 'Emma', 'age': 28}

在这个例子中,我们定义了一个Person类,并定义了一个person_decoder函数用于自定义反序列化。该函数检查传入的字典是否包含name和age键,如果包含,则创建并返回一个Person实例;否则,直接返回原字典。

在调用json.loads()函数时,我们通过object_hook参数指定了person_decoder函数,这样JSON字符串中的对象就会被解析为Person实例。

处理循环引用

在序列化过程中,如果对象之间存在循环引用(例如,一个对象包含另一个对象的引用,而另一个对象又包含回第一个对象的引用),则默认情况下json.dumps()会抛出TypeError异常。为了处理循环引用,可以使用default参数自定义序列化函数,并在函数中检测循环引用。

然而,更简单的方法是使用json模块的JSONEncoder类,并覆盖其default方法。同时,可以利用一个WeakKeyDictionary来跟踪已经序列化的对象,从而避免循环引用。

以下是一个处理循环引用的示例:

import json  
from collections.abc import Mapping  
from weakref import WeakKeyDictionary  
  
class JSONEncoderWithCircularRef(json.JSONEncoder):  
    def __init__(self, *args, **kwargs):  
        super().__init__(*args, **kwargs)  
        self._visited = WeakKeyDictionary()  
  
    def default(self, obj):  
        if id(obj) in self._visited:  
            return "<circular reference detected>"  
        self._visited[obj] = None  
        if isinstance(obj, Mapping):  
            return dict(obj)  # 或者进行其他处理  
        # 可以在这里添加对其他类型的处理  
        return json.JSONEncoder.default(self, obj)  
  
# 示例对象,包含循环引用  
class Node:  
    def __init__(self, value):  
        self.value = value  
        self.next = None  
  
node1 = Node(1)  
node2 = Node(2)  
node1.next = node2  
node2.next = node1  # 循环引用  
  
# 序列化包含循环引用的对象  
json_string = json.dumps(node1, cls=JSONEncoderWithCircularRef, indent=4)  
print(json_string)

注意,上面的代码示例中,我们并没有为Node类提供完整的序列化逻辑(例如,如何将Node对象转换为字典)。

在实际应用中,你可能需要根据你的Node类的结构来实现更具体的序列化逻辑。同时,上面的代码只是简单地返回了一个字符串"<circular reference detected>"来表示循环引用,你也可以根据需要进行更复杂的处理。

此外,虽然WeakKeyDictionary可以用来跟踪已经访问过的对象以避免循环引用,但请注意,它不会阻止对象被垃圾回收。

因此,如果你的对象图非常大且复杂,并且你希望在序列化后释放内存,那么你可能需要采用其他策略来管理你的对象图。

总结

json模块是Python中处理JSON数据的强大工具。通过合理使用其提供的函数和类,你可以轻松地在Python对象和JSON数据之间进行转换。同时,通过自定义序列化和反序列化函数,你还可以扩展json模块的功能以处理更复杂的对象类型。


原文地址:https://blog.csdn.net/weixin_43856625/article/details/143504429

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!