Python Json模块详解:标准库应用指南

一、模块简介

        json库是Python内置的一个标准库,用于在Python对象和JSON数据之间进行序列化和反序列化,json库在日常的开发中经常用到,它广泛应用于接口开发、配置管理、数据交换等场景。
        由于日常开发中会经常用到这个库,今天闲来无事,打算来总结一下一些常用的json库的一些方法以及参数的含义。
        本文会结合代码以及运行结果的方式来帮助你理解并真的会用他!

二、Json库的使用

 首先,json库是python内置的一个库,我们直接调用即可

import json

接下来,我们一起来看看json将Python对象进行序列化的两种方法

(后续标题会使用这种方法,可以简要了解一下*args和**kwargs,如下注)

注:在 Python 中,*args 和**kwargs 用于函数定义中接收可变数量的参数。*args表示接收任意数量的位置参数,函数内部将其打包为一个元组;而**kwargs 则用于接收任意数量的关键字参数,函数内部将其打包为一个字典。它们常用于不确定传入参数数量的场景,能够提高函数的灵活性与通用性。例如:def func(*args, **kwargs):就可以同时接收多个普通参数和命名参数。

2.1 序列化

2.1 json.dump(*args, **kwargs)方法

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 格式,并 写入到类文件对象 fp

其中各个参数的详解如下

参数 含义 默认值
obj 要序列化的 Python 对象(如 dictlist 等)
fp 类文件对象,必须支持 .write() 方法,如打开的文件句柄
skipkeys 如果为 True,则字典中非字符串键会被跳过,否则会报 TypeError False
ensure_ascii 如果为 True,所有非 ASCII 字符会转义为 \uXXXX,否则输出原字符 True
check_circular 如果为 False,允许循环引用,否则报 ValueError True
allow_nan 如果为 True,允许 NaN, Infinity, -Infinity 并序列化为对应标识符,否则报 ValueError True
cls 自定义的 JSONEncoder 子类,用于扩展序列化行为 None
indent 缩进空格数;若为 None 则输出紧凑版;若为非负整数,则美化输出 None
separators (item_sep, key_sep) 元组,定义项与项、键与值间分隔符;默认 (',', ': ') None
default 可调用,遇到不可序列化对象时回调,将其转为可序列化类型 None
sort_keys 如果为 True,字典的键会被排序后输出 False

        其中很常用的应该是obj,fp,ensure_ascii(想输出中文,一般会置为False),indent(调整输出缩进,可以使json格式更美观),sort_keys(用作排序)。

以下是一个简单的调用示例,将 Python 对象写入到 JSON 文件中。

import json

# 创建一个字典对象
data = {
    '名字': 'my', 
    '年龄': 20, 
    'tags': ['python', '博客']
}

# 将字典写入到 data.json 文件中
with open('out.json', 'w', encoding='utf-8') as f:
    json.dump(
        data, f,
        ensure_ascii=False,    # 保留中文
        indent=2,              # 缩进 2 格
        sort_keys=True         # 字段按字母排序
    )

运行过后会生成一个out.json文件,内容如下

        想要深刻的理解这些常用的参数,不妨我们试试修改他们,如果ensure_ascii置为True会是什么样子,非ASCii字符就会转为\uXXXX,如下图所示

当我不适用缩进,也就是将indent置为0,会怎么样呢?

        就会变成这样,是不是没有有缩进的看着舒服呢?当不按字段排序也就是sort_keys置为False时,会是什么样子呢?

由这些可以知道,很好的利用这些参数,可以让可读性很强,观感更舒服。

总结:

  • Python 对象写入到 JSON 文件
  • 适合将数据保存为 JSON 格式的配置文件、缓存数据等
  • indent以及sort_keys参数让文件内容更可读,常用于调试或用户可读场景
  • 2.2 json.dumps(*args, **kwargs)方法

    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) → str

    Python 对象编码为 JSON 格式的 字符串

    参数说明:和json.dump()几乎完全一致,区别是返回一个字符串,而不是写入文件。

    以下是一个简单的调用示例,将 Python 对象转换成 JSON 字符串。

    import json
    
    # 同样的 Python 对象
    data = {
        '名字': 'my', 
        '年龄': 20, 
        'tags': ['python', '博客']
    }
    
    # 将 Python 对象转为 JSON 字符串
    json_str = json.dumps(data, ensure_ascii=False, indent=2)
    
    # 打印 JSON 字符串
    print(json_str)
    

    打印内容如下

     总结:

  • Python 对象转换成 JSON 字符串
  • dumps() 的结果是一个字符串,常用于传输数据(如发送给接口、保存数据库)
  • dump() 相比,区别是是否“写入文件”
  •  2.2 反序列化

    2.2.1 json.load(*args, **kwargs)方法

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

    从类文件对象 fp读取 JSON 数据,并转换为 Python 对象

     其中各个参数的详解如下

    参数名 类型 说明
    fp 文件对象 打开并读取的 JSON 文件对象
    cls type 自定义的 JSONDecoder 子类
    object_hook function 将 JSON 对象(dict)转换为其他类型的函数
    parse_float function 自定义将 JSON 浮点数转换为其他类型(如 Decimal)
    parse_int function 自定义将 JSON 整数转换为其他类型(如 float)
    parse_constant function 自定义解析常量 NaNInfinity
    object_pairs_hook function 代替 object_hook,保留键值顺序(如 OrderedDict)

     一般只需用到fp参数,其他参数可根据自己的需求来使用。

    以下是一个简单的调用示例,从 JSON 文件中读取数据为 Python 对象。

    import json
    
    # 假设已经存在out.json文件,并且文件内容是:
    # data = {
    #     '名字': 'my', 
    #     '年龄': 20, 
    #     'tags': ['python', '博客']
    # }
    
    # 从文件读取并转换为 Python 对象
    with open('out.json', 'r', encoding='utf-8') as f:
        loaded_data = json.load(f)
    
    # 打印读取到的 Python 对象
    print(loaded_data)
    

     打印内容如下

     总结

  • 从 JSON 文件中读取数据为 Python 对象

  • 常用于读取配置、存储的数据文件

  • 注意文件路径、编码要匹配

  •  2.2.2 json.loads(*args, **kwargs)方法

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

    将 JSON 格式的 字符串 反序列化为 Python 对象

    参数说明:与load()相同,但第一个参数是字符串 。

     以下是一个简单的调用示例,将 JSON 字符串解析成 Python 对象。

    import json
    
    # 一个合法的 JSON 字符串
    json_str = '{"名字": "my", "年龄": 20, "tags": ["python", "博客"]}'
    
    # 转换为 Python 字典
    data = json.loads(json_str)
    
    # 访问其中的数据
    print(data['名字'])     # 输出:my
    print(data['年龄'])      # 输出:20
    print(data['tags'])  # 输出:博客

    打印内容如下

    总结

  • 将 JSON 字符串解析成 Python 对象
  • JSON 中的 truefalsenull 会自动映射为 Python 的 TrueFalseNone
  • 2.3 总结对比 

    分类 函数名 作 用 数据来源 数据目标 常用参数
    ✅ 序列化 json.dump() 将 Python 对象写入到 JSON 文件 Python 对象 文件(.json fp, indent, ensure_ascii, default, sort_keys
    ✅ 序列化 json.dumps() 将 Python 对象转换为 JSON 字符串 Python 对象 字符串(str) indent, ensure_ascii, default, sort_keys
    🔄 反序列化 json.load() JSON 文件中读取内容为 Python 对象 文件(.json Python 对象(dict等) fp, object_hook, parse_float, parse_int
    🔄 反序列化 json.loads() JSON 字符串 转换为 Python 对象 字符串(str) Python 对象(dict等) object_hook, parse_float, parse_int

    三、进阶用法:default 与 object_hook

    3.1 default 参数 —— 定制化序列化(Python ➜ JSON)

            当我们在使用json.dump()或json.dumps()将 Python 对象转换为 JSON 时,如果对象中包含 JSON 标准不支持的类型(如datetime、自定义类对象等),就会抛出错误。这时就可以通过default参数,告诉 JSON 如何处理这些类型

    json.dumps(obj, default=custom_function)
    

    参数说明:

  • obj:要序列化的 Python 对象
  • default:一个函数,接收一个不能序列化的对象,返回一个可被序列化的类型(如:字符串、数字、列表、字典)
  •  以下是一个简单示例,序列化一个datetime对象。

    import json
    from datetime import datetime
    
    # 原始数据
    data = {
        "event": "我的第一篇博客发表时间",
        "time": datetime(2025, 6, 8, 15, 0)
    }
    
    # 自定义转换函数
    def datetime_serializer(obj):
        if isinstance(obj, datetime):
            return obj.isoformat()  # 转为标准字符串
        raise TypeError(f"无法序列化类型: {type(obj)}")
    
    # 使用 default 序列化
    json_str = json.dumps(data, default=datetime_serializer, ensure_ascii=False, indent=2)
    print(json_str)
    

    打印内容如下

    如果不进行该定制化序列化,该datetime就是JSON标准所不支持的类型,而提供了default的参数,会告诉JSON如何处理这些数据(也就是所定义的datetime_seriallizer函数)则会报错,而定制化序列化很好的解决了这个问题。下面我们来一个进阶例子。

    以下是一个示例,序列化自定义类对象。

    class Student:
        def __init__(self, name, score):
            self.name = name
            self.score = score
    
    student = Student("小z", 100)
    
    def student_serializer(obj):
        if isinstance(obj, Student):
            return {"name": obj.name, "score": obj.score}
        raise TypeError("无法序列化的对象")
    
    json_str = json.dumps(student, default=student_serializer, ensure_ascii=False)
    print(json_str)

    打印内容如下

     总结:

            default参数用于解决 无法被 JSON 默认序列化的对象(如自定义类、datetime等),它接收一个函数,将特殊对象转换为可被 JSON 接受的标准格式(如字典或字符串)。常用于json.dumps()和json.dump()中。

    3.2 object_hook 参数:定制化反序列化(JSON ➜ Python 对象)

            当我们在使用json.load()或json.loads()将 JSON 字符串转为 Python 对象时,默认只返回 dict 类型。但我们可以通过object_hook参数,自定义将 JSON 字典转换为 Python 中的类实例,实现“还原成对象”。

    json.loads(json_str, object_hook=custom_decoder)
    

    参数说明:

  • 待解析的 JSON 字符串
  • 一个函数,它会接收反序列化后的每一个 JSON 对象(即字典dict),并返回转换后的 Python 对象
    (它会在 JSON 嵌套结构中从最内层到外层递归调用)
  •  以下是一个进阶示例,将 JSON 反序列化为自定义类

    class Student:
        def __init__(self, name, score):
            self.name = name
            self.score = score
    
    # JSON 字符串
    json_str = '{"name": "小z", "score": 100}'
    
    # 自定义解码函数
    def dict_to_student(d):
        return Student(d['name'], d['score'])
    
    # 使用 object_hook 解码
    student = json.loads(json_str, object_hook=dict_to_student)
    print(student.name)   # 小z
    print(student.score)  # 100
    

    打印内容如下

            经过我们前面的学习,我们知道json.loads()会将json格式的数据反序列化为python对象,而我们所加的这个参数object_hook=dict_to_student,就等价于一个映射函数,将经典的python对象映射为我们所自定义的类对象。方便我们可以直接调用自定义类的功能。

    下面我们来一个进阶例子,将带类型字段的 JSON 动态还原多个对象类型。

    class Student:
        def __init__(self, name, score):
            self.name = name
            self.score = score
    
    class Teacher:
        def __init__(self, name, subject):
            self.name = name
            self.subject = subject
    
    json_str = '''
    [
        {"type": "student", "name": "小z", "score": 100},
        {"type": "teacher", "name": "小l", "subject": "数学"}
    ]
    '''
    
    def smart_decoder(d):
        if d.get("type") == "student":
            return Student(d["name"], d["score"])
        elif d.get("type") == "teacher":
            return Teacher(d["name"], d["subject"])
        return d  # 默认返回 dict
    
    data = json.loads(json_str, object_hook=smart_decoder)
    
    for obj in data:
        print(type(obj), vars(obj))  # 输出对象类型和属性字典

    打印内容如下

    这里只是在前者的例子上多加了一个自定义类,在映射函数中多加了一个判断逻辑。 

    3.3 总结对比

    参数名 用于方法 用途 输入数据类型 输出数据类型
    default dumps() / dump() 自定义不可序列化对象的转换 非 JSON 类型对象(如类) 可序列化对象(如字典、字符串)
    object_hook loads() / load() 自定义 JSON 字典的解析 JSON 对象(dict) Python 对象(如类实例)

     比较常见的场景和建议

    场景 建议用法
  • 序列化 datetime、自定义类
  • default 参数
    还原为类对象 object_hook 参数
    多类型自动识别 结合 type 字段与 object_hook 实现
    嵌套结构还原 object_hook 会自动递归调用

    四、注意事项

  • Python JSON
    dict object
    list, tuple array
    str string
    int, float number
    True/False true/false
    None null
  • dumps() 与 loads() 用于字符串处理,dump() 与 load() 用于文件处理
  • 不支持直接序列化自定义类、函数、集合等 —— 需借助 default 参数手动转换
  •  五、结语

            相信今天所讲的这些在你的json生涯中已经绰绰有余了,json模块完结撒花!!!        

            这是我写博客的第二篇,也是第二天,想着每天抽出来一点闲暇时间来写一些东西,顺便也丰富一下自己的逻辑表达能力,以及知识储备能力,后续会陆续推出其他各种模块包的经典用法,等有闲时间了,当下时间有点紧,其他方面的东西在当下不适合写,等今年过了,明年开始尝试写一些项目实战还有原理性的东西!

    作者:小z..

    物联沃分享整理
    物联沃-IOTWORD物联网 » Python Json模块详解:标准库应用指南

    发表回复