pin_drop当前位置:知识文库 ❯ 图文
Python json.loads详解 - JSON解码与自定义解析技巧
一、概述
json.loads() 是 json 模块中将 JSON 格式字符串反序列化为 Python 对象的函数。函数名中的 "loads" 代表 "load string",即从字符串加载数据。loads() 是处理 API 响应、配置文件内容、网络数据等 JSON 文本的核心函数,支持自定义解码逻辑和对象钩子。
二、语法
代码示例
import json
obj = json.loads(s, *, cls=None, object_hook=None,
parse_float=None, parse_int=None,
parse_constant=None, object_pairs_hook=None, **kw)三、参数说明
四、返回值
返回与 JSON 对应的 Python 对象。JSON object 映射为 dict,array 映射为 list,string 映射为 str,number 映射为 int 或 float,true/false/null 映射为 True/False/None。
五、代码示例
示例1:基本解码
代码示例
import json
# 解码各种JSON类型
json_strings = [
'{"name": "张三", "age": 25}',
'[1, 2, 3, "hello"]',
'"Hello World"',
'42',
'3.14',
'true',
'null',
]
for s in json_strings:
result = json.loads(s)
print(f" {s:40s} -> {result!r:30s} (类型: {type(result).__name__})")输出:
代码示例
{"name": "张三", "age": 25} -> {'name': '张三', 'age': 25} (类型: dict)
[1, 2, 3, "hello"] -> [1, 2, 3, 'hello'] (类型: list)
"Hello World" -> 'Hello World' (类型: str)
42 -> 42 (类型: int)
3.14 -> 3.14 (类型: float)
true -> True (类型: bool)
null -> None (类型: NoneType)示例2:自定义解析函数
代码示例
import json
from decimal import Decimal
json_str = '{"price": 19.99, "count": 100, "ratio": 0.333}'
# 默认解析(float精度问题)
default_result = json.loads(json_str)
print(f"默认: price = {default_result['price']}")
print(f" 类型: {type(default_result['price']).__name__}")
# 使用Decimal解析浮点数
decimal_result = json.loads(json_str, parse_float=Decimal)
print(f"\nDecimal: price = {decimal_result['price']}")
print(f" 类型: {type(decimal_result['price']).__name__}")
# 自定义整数解析
str_int_result = json.loads(json_str, parse_int=str)
print(f"\n字符串整数: count = {str_int_result['count']!r}")
print(f" 类型: {type(str_int_result['count']).__name__}")输出:
代码示例
默认: price = 19.99
类型: float
Decimal: price = 19.99
类型: Decimal
字符串整数: count = '100'
类型: str示例3:object_hook 自定义解码
代码示例
import json
from datetime import datetime
def datetime_hook(obj):
"""自动将ISO格式日期字符串转换为datetime对象"""
for key, value in obj.items():
if isinstance(value, str):
try:
obj[key] = datetime.fromisoformat(value)
except ValueError:
pass
return obj
json_str = '''
{
"name": "项目A",
"created_at": "2024-01-15T14:30:00",
"deadline": "2024-06-30",
"status": "进行中"
}
'''
# 不使用hook
result_no_hook = json.loads(json_str)
print("不使用hook:")
print(f" created_at类型: {type(result_no_hook['created_at']).__name__}")
# 使用hook
result_with_hook = json.loads(json_str, object_hook=datetime_hook)
print("\n使用hook:")
print(f" created_at类型: {type(result_with_hook['created_at']).__name__}")
print(f" created_at值: {result_with_hook['created_at']}")输出:
代码示例
不使用hook:
created_at类型: str
使用hook:
created_at类型: datetime
created_at值: 2024-01-15 14:30:00六、实际应用场景
-
API 响应解析:将 HTTP 请求返回的 JSON 字符串解析为 Python 对象
-
配置文件读取:读取 JSON 格式的配置文件内容
-
数据类型精确控制:使用
parse_float避免 float 精度问题,使用object_hook自动转换日期等类型
七、注意事项
注意1:
json.loads()只接受有效的 JSON 字符串,无效格式会引发json.JSONDecodeError(Python 3.5+),应做好异常处理。
注意2:JSON 数字中的浮点数在 Python 中默认解析为
float,存在精度问题。金融场景应使用parse_float=Decimal。
注意3:
object_hook在每个 JSON object 解码完成后被调用,嵌套对象会从内到外依次触发。
提示:Python 3.6+ 的
json.loads()也接受bytes和bytearray类型作为输入,无需预先解码。
八、相关方法对比
九、小结
-
json.loads()将 JSON 字符串反序列化为 Python 对象,是最常用的 JSON 解码函数 -
支持自定义解析:
parse_float(浮点精度)、parse_int(整数类型)、object_hook(对象转换) -
无效 JSON 会引发
JSONDecodeError,应做好异常捕获 -
金融等精度敏感场景应使用
parse_float=Decimal避免浮点精度损失
十、练习题
练习1
编写一个函数 safe_json_loads(s),捕获 JSONDecodeError 并返回 (result, error) 元组,成功时 error 为 None。
练习2
编写一个 object_hook 函数,自动将 JSON 中的下划线键名转换为驼峰命名(如 user_name -> userName)。
练习3
编写一个函数,使用 parse_float=Decimal 解析 JSON,验证浮点数精度在加减运算中的差异。
小贴士
object_hook 会在解码过程中对每一个 JSON 对象调用一次。如果你的 JSON 数据包含嵌套对象,object_hook 会从最内层的对象开始逐层向外调用。这意味着你可以利用这一特性,只转换特定层级的数据结构。另外,object_pairs_hook 接收有序键值对列表,适合需要保留原始键顺序的场景。
常见问题
json.loads() 可以解析 bytes 类型吗?
可以。Python 3.6+ 起,json.loads() 支持 str、bytes 和 bytearray 类型作为输入。对于 bytes 类型,会自动使用 UTF-8 解码,无需手动调用 decode()。
parse_float=Decimal 的性能影响大吗?
Decimal 的运算速度比 float 慢,但在金融和货币等精度敏感场景是值得的。如果数据量非常大且精度要求不高,建议保持默认的 float 解析以获得更好的性能。
object_hook 和 object_pairs_hook 有什么区别?
object_hook 接收已经转换为 dict 的对象,而 object_pairs_hook 接收有序键值对列表 [(key, value), ...]。如果同时设置了两个参数,object_pairs_hook 优先。使用 object_pairs_hook 可以保留 JSON 中的键值对原始顺序。
如何处理无效的 JSON 字符串?
使用 try-except 捕获 json.JSONDecodeError 异常。异常对象包含 msg(错误信息)、lineno(行号)和 colno(列号)属性,可以用于精确定位和报告错误位置。
本文涉及AI创作
内容由AI创作,请仔细甄别