查看: 476|回复: 0

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

[复制链接]
发表于 4 小时前 | 显示全部楼层 |阅读模式
Python 处理 JSON 的入口是标准库 json 模块:dumps/loads 面向字符串,dump/load 面向文件;复杂对象可通过继承 JSONEncoder/JSONDecoder 并配合 cls 参数完成定制。下面按实际开发中最常见的四类操作整理。

一、字符串编解码:dumps 与 loads
  1. import json
  2. data = {'name': 'Alice', 'age': 25}
  3. json_str = json.dumps(data)
  4. print(json_str)  # 输出:{"name": "Alice", "age": 25}
  5. json_str = '{"name": "Alice", "age": 25}'
  6. data = json.loads(json_str)
  7. print(data)  # 输出:{'name': 'Alice', 'age': 25}
复制代码

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

二、文件读写:load 与 dump
  1. import json
  2. with open('data.json', 'r') as f:
  3.     data = json.load(f)
  4. print(data)
  5. data = {'name': 'Alice', 'age': 25}
  6. with open('data.json', 'w') as f:
  7.     json.dump(data, f)
复制代码

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

三、自定义编码器和解码器
当对象不是 dict/list/字符串/数字这些 JSON 原生类型时,直接 dumps 会报错。原文做法是定义 Person,再继承 json.JSONEncoder 重写 default;解码侧继承 json.JSONDecoder 重写 decode,并在 dumps/loads 时用 cls 指定。
  1. import json
  2. class Person:
  3.     def __init__(self, name, age):
  4.         self.name = name
  5.         self.age = age
  6. class PersonEncoder(json.JSONEncoder):
  7.     def default(self, obj):
  8.         if isinstance(obj, Person):
  9.             return {'name': obj.name, 'age': obj.age}
  10.         return super().default(obj)
  11. class PersonDecoder(json.JSONDecoder):
  12.     def decode(self, s):
  13.         data = super().decode(s)
  14.         if 'name' in data and 'age' in data:
  15.             return Person(data['name'], data['age'])
  16.         return data
  17. person = {'person': Person('Alice', 25)}
  18. json_str = json.dumps(person, cls=PersonEncoder)
  19. print(json_str)  # 输出:{"person": {"name": "Alice", "age": 25}}
  20. json_data = '{"name": "Alice", "age": 25}'
  21. obj = json.loads(json_data, cls=PersonDecoder)
  22. 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 值
  1. import json
  2. json_str = '{"name": "Alice", "age": 25}'
  3. data = json.loads(json_str)
  4. print(data['name'])  # 输出:Alice
  5. print(data['age'])   # 输出:25
  6. data['age'] = 26
  7. json_str = json.dumps(data)
  8. print(json_str)  # 输出:{"name": "Alice", "age": 26}
复制代码

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

五、用 get 提供默认值,避免 KeyError
  1. import json
  2. json_str = '{"name": "Alice", "age": 25}'
  3. json_obj = json.loads(json_str)
  4. name = json_obj.get('name', 'Unknown')
  5. print(name)  # 输出:Alice
  6. gender = json_obj.get('gender', 'Unknown')
  7. print(gender)  # 输出:Unknown
复制代码

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

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

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-9-18 17:03 , Processed in 0.029357 second(s), 17 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部