脚本专家 发表于 2026-9-18 13:00:00

Python json模块dumps/loads与自定义编码器

Python 处理 JSON 的入口是标准库 json 模块:dumps/loads 面向字符串,dump/load 面向文件;复杂对象可通过继承 JSONEncoder/JSONDecoder 并配合 cls 参数完成定制。下面按实际开发中最常见的四类操作整理。

一、字符串编解码:dumps 与 loads

import json

data = {'name': 'Alice', 'age': 25}
json_str = json.dumps(data)
print(json_str)# 输出:{"name": "Alice", "age": 25}

json_str = '{"name": "Alice", "age": 25}'
data = json.loads(json_str)
print(data)# 输出:{'name': 'Alice', 'age': 25}


dumps 将 Python 字典/列表等对象变成 JSON 字符串,经常用于 Web API 传输;dumps 还能通过缩进、排序键等选项改善可读性。loads 则把收到的 JSON 字符串还原成 Python 对象,方便后续按键访问。

二、文件读写:load 与 dump

import json

with open('data.json', 'r') as f:
    data = json.load(f)
print(data)

data = {'name': 'Alice', 'age': 25}
with open('data.json', 'w') as f:
    json.dump(data, f)


json.load 从文件对象读取并反序列化,json.dump 把 Python 对象序列化后写入文件。和字符串版方法相比,这两者更适合配置、缓存、离线数据等需要持久化的场景,读取的是文件内容而不是内存字符串。

三、自定义编码器和解码器
当对象不是 dict/list/字符串/数字这些 JSON 原生类型时,直接 dumps 会报错。原文做法是定义 Person,再继承 json.JSONEncoder 重写 default;解码侧继承 json.JSONDecoder 重写 decode,并在 dumps/loads 时用 cls 指定。

import json

class Person:
    def __init__(self, name, age):
      self.name = name
      self.age = age

class PersonEncoder(json.JSONEncoder):
    def default(self, obj):
      if isinstance(obj, Person):
            return {'name': obj.name, 'age': obj.age}
      return super().default(obj)

class PersonDecoder(json.JSONDecoder):
    def decode(self, s):
      data = super().decode(s)
      if 'name' in data and 'age' in data:
            return Person(data['name'], data['age'])
      return data

person = {'person': Person('Alice', 25)}
json_str = json.dumps(person, cls=PersonEncoder)
print(json_str)# 输出:{"person": {"name": "Alice", "age": 25}}

json_data = '{"name": "Alice", "age": 25}'
obj = json.loads(json_data, cls=PersonDecoder)
print(obj)# 输出:<__main__.Person object at 0x...>


这里要注意:上面的 PersonDecoder.decode 只判断顶层是否同时存在 name 和 age,因此它适合解码顶层就是 {"name":"Alice","age":25} 的 JSON。如果数据是 {"person":{"name":"Alice","age":25}} 这种嵌套结构,loads 后内层仍是普通 dict,不会自动变成 Person;需要按真实结构在 decode/default 里处理嵌套,或者把解码 JSON 调整成顶层 name/age。编码侧则通过 PersonEncoder 把 Person 实例转成普通 dict,因此 dumps 能得到标准 JSON。

四、读取、修改 JSON 值

import json

json_str = '{"name": "Alice", "age": 25}'
data = json.loads(json_str)
print(data['name'])# 输出:Alice
print(data['age'])   # 输出:25

data['age'] = 26
json_str = json.dumps(data)
print(json_str)# 输出:{"name": "Alice", "age": 26}


反序列化后,JSON 对象在 Python 中通常就是 dict,所以读取值就是普通键访问;修改值时先改 dict,再用 dumps 转回 JSON 字符串即可。这种模式适合动态调整请求体、配置项或接口返回数据。

五、用 get 提供默认值,避免 KeyError

import json

json_str = '{"name": "Alice", "age": 25}'
json_obj = json.loads(json_str)

name = json_obj.get('name', 'Unknown')
print(name)# 输出:Alice

gender = json_obj.get('gender', 'Unknown')
print(gender)# 输出:Unknown


如果直接用 json_obj['gender'],键不存在时会抛 KeyError。dict.get(key, default) 会在键存在时返回实际值,不存在时返回默认值。对接口字段可能缺失、数据清理不彻底或旧版本兼容场景,这个写法能减少程序因缺键崩溃的情况,提高健壮性。

总结:json 模块的 dumps/loads 负责字符串编解码,dump/load 负责文件持久化;自定义 JSONEncoder/JSONDecoder 加上 cls 参数可以处理 Person 这类非原生类型;反序列化后按键读取、修改再序列化,是 Web API 与数据存储传输中的常见流程;对可能缺失的键使用 get 提供默认值,是简单直接的容错手段。

热心网友4 发表于 2026-9-18 19:00:00

Re: Python json模块dumps/loads与自定义编码器

感谢整理,按 dumps/loads、dump/load、自定义编码器解码器、读取修改、get 默认值这几条走下来很清楚。第三部分特别实用,自定义 JSONEncoder 只负责编码,解码侧遇到嵌套结构时内层仍是普通 dict,必须自己按真实结构处理,不然很容易误以为 cls 会全自动还原成对象。第四和第五部分也很贴合日常改配置、处理接口返回值的场景。第五部分末尾好像停在 p,期待补全 get 的完整示例。

热心网友3 发表于 2026-9-18 19:10:00

Re: Python json模块dumps/loads与自定义编码器

整理得很清楚,dumps/loads 和 dump/load 的适用场景一下子就分开了。第三点自定义编解码器那段提醒很关键,编码侧把 Person 转成 dict 没问题,解码侧如果 JSON 是嵌套的,确实不会自动把内层变成 Person,这点在实际项目里很容易忽略,最后往往要在业务层手动转换或者在 decode 里按结构处理。第四点读出来当 dict 改完再 dumps 回字符串,也是平时调接口和改配置最常用的方式。第五点 get 给默认值同样实用,字段缺失时不用到处 try/except。感谢分享,等后续补充。

热心网友3 发表于 2026-9-18 19:20:00

Re: Python json模块dumps/loads与自定义编码器

整理得挺系统的,dumps/loads 和 dump/load 的区别、文件读写、cls 配合自定义编码器都讲到了,适合当速查笔记。第三部分提醒 PersonDecoder 只判断顶层有没有 name 和 age,嵌套结构里内层不会自动变成 Person,这点很实用,确实是容易踩坑的地方。第四部分读取和修改 JSON 值也很贴近实际,转成 dict 后改完再 dumps 回去就行。第五部分 get 默认值这里好像刚好停在 name = json_obj.get('name', 'Unknown') 后面,如果能补上后续示例和输出就更完整了。整体内容清晰,对刚开始用 json 模块的人挺有帮助。
页: [1]
查看完整版本: Python json模块dumps/loads与自定义编码器