🍀 前言
博客地址:
👋 简介
JSON 是用于存储和交换数据的语法,是一种轻量级的数据交换格式。经常用于接口数据传输、序列化、配置文件等。本章介绍下 Python 是如何通过内置json库操作 JSON 数据的。
📖 正文
1 数据操作
1.1 dumps
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)
参数详解:
obj
:要转换为 JSON 字符串的 Python 对象(必填);skipkeys
: 如果为 True,则字典的键中包含非字符串对象时将跳过而不是引发 TypeError,默认为 False;ensure_ascii
:如果为 True,则所有非 ASCII 字符将以 \uXXXX 的形式进行转义,默认为 True;check_circular
:如果为 True,则检查循环引用(例如,一个对象引用了自己),默认为 True;allow_nan
:如果为 True,则允许 NaN、Infinity 和 -Infinity 出现在 JSON 字符串中,默认为 True;cls
:用于自定义 JSON 编码的类,默认为 None,通常可以指定 JSONEncoder 的子类;indent
:控制生成的 JSON 字符串的缩进。可以是一个整数表示缩进空格数,或者是一个字符串表示使用的缩进字符,默认为 None(表示不格式化输出);separators
:用于控制不同部分之间的分隔符,默认为 (', ', ': ');default
:用于处理不可序列化对象的函数。如果指定,该函数将在尝试序列化无法处理的对象时被调用,并返回一个可序列化的版本,默认为 None;sort_keys
:如果为 True,则在输出时按字典键的顺序对 JSON 对象进行排序,默认为 False
import json
data = {
"name": "张三",
"age": 18,
"city": "成都",
"is_student": False,
"grades": [85, 92, 78],
"address": {
"street": "成华区二仙桥",
"city": "四川省成都市",
}
}
res = json.dumps(data, ensure_ascii=False)
print(type(res))
print(res)
# <class 'str'>
# {"name": "张三", "age": 18, "city": "成都", "is_student": false, "grades": [85, 92, 78], "address": {"street": "成华区二仙桥", "city": "四川省成都市"}}
1.2 loads
json.loads(s, *, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)
,参数详解:
s
:要解析为 Python 对象的 JSON 字符串(必填);cls
:用于自定义 JSON 编码的类,默认为 None,通常可以指定 JSONEncoder 的子类;object_hook
:用于转换字典对象的函数。如果指定,该函数将在每个字典对象上调用,并返回一个转换后的结果,默认为 None;parse_float
:用于解析浮点数的函数。如果指定,该函数将在每个浮点数上调用,并返回一个转换后的结果,默认为 None;parse_int
:用于解析整数的函数。如果指定,该函数将在每个整数上调用,并返回一个转换后的结果,默认为 None;parse_constant
:如果指定,应该是 float,int 或 str,它将替换 JSON 字符串中的 NaN,Infinity 和 -Infinity,默认为 None;object_pairs_hook
:用于转换字典对象的函数,与 object_hook 不同,它接受键值对作为参数,默认为 None;**kw
:可变参数。
content = '''{
"name": "张三",
"age": 18,
"city": "成都",
"is_student": false,
"grades": [
85,
92,
78
],
"address": {
"street": "成华区二仙桥",
"city": "四川省成都市"
}
}
'''
res = json.loads(content)
print(type(res))
print(res)
# <class 'dict'>
# {'address': {'city': '四川省成都市', 'street': '成华区二仙桥'}, 'age': 18, 'city': '成都', 'grades': [85, 92, 78], 'is_student': False, 'name': '张三'}
2 文件操作
1.1 dump
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)
,参数详解:
obj
:要写入 JSON 文件的 Python 对象(必填);fp
:文件对象(通常通过 open() 函数获得),用于写入 JSON 数据(必填);**kw
:可变参数。
其余参数与dumps
方法的相同
data = {
"name": "张三",
"age": 18,
"city": "成都",
"is_student": False,
"grades": [85, 92, 78],
"address": {
"street": "成华区二仙桥",
"city": "四川省成都市",
}
}
with open('test.json', 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=4)
执行完以上代码,在同级目录下生成一个test.json文件
{
"name": "张三",
"age": 18,
"city": "成都",
"is_student": false,
"grades": [
85,
92,
78
],
"address": {
"street": "成华区二仙桥",
"city": "四川省成都市"
}
}
1.2 load
json.load(fp, *, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)
,参数详解:
fp
:文件对象(通常通过 open() 函数获得),用于读取 JSON 数据(必填)。
其余参数与dumps
方法的相同
with open('test.json', 'r', encoding='utf-8') as f:
res = json.load(f)
print(type(res))
print(res)
# <class 'dict'>
# {'name': '张三', 'age': 18, 'city': '成都', 'is_student': False, 'grades': [85, 92, 78], 'address': {'street': '成华区二仙桥', 'city': '四川省成都市'}}
通过执行结果发现,从文件读取的json数据,在python中转化成了dict。
3 工具类封装
from typing import Text, Union, Dict, List, Any
import json
# 类型别名
JSONType = Union[Dict[str, Any], List[Dict[str, Any]], str]
class JSONTools:
@staticmethod
def to_string(data: JSONType, *, indent: int = None, ensure_ascii: bool = False) -> Text:
"""
将 Python 对象编码为 JSON 字符串
:param data: 数据
:param indent: 缩进,默认None,显示一行数据
:param ensure_ascii: 是否保证中文输出为Unicode,默认False,输出正常中文
:return:
"""
return json.dumps(data, indent=indent, ensure_ascii=ensure_ascii)
@staticmethod
def to_json(json_string: Text) -> JSONType:
"""
将 JSON 字符串解码为 Python 对象
:param json_string: json字符串
:return:
"""
try:
return json.loads(json_string)
except json.decoder.JSONDecodeError as e:
return f"json数据格式不正确,请检查后重试。错误提示:{e}"
@staticmethod
def to_file(data: JSONType, file_path: str, *, indent: int = None, ensure_ascii: bool = False) -> None:
"""
将 Python 对象编码并写入 JSON 文件
:param data: 数据
:param file_path: 文件路径
:param indent: 缩进,默认None,显示一行数据
:param ensure_ascii: 是否保证中文输出为Unicode,默认False,输出正常中文
:return:
"""
with open(file_path, 'w', encoding='utf-8') as file:
json.dump(data, file, indent=indent, ensure_ascii=ensure_ascii)
@staticmethod
def from_file(file_path: str) -> JSONType:
"""
从 JSON 文件中读取并解码为 Python 对象
:param file_path: 文件路径
:return:
"""
try:
with open(file_path, 'r', encoding='utf-8') as file:
return json.load(file)
except json.decoder.JSONDecodeError as e:
return f"json数据格式不正确,请检查后重试。错误提示:{e}"
if __name__ == '__main__':
data = {
"name": "张三",
"age": 18,
"city": "成都",
"is_student": False,
"grades": [85, 92, 78],
"address": {
"street": "成华区二仙桥",
"city": "四川省成都市",
}
}
# json 转 string
content = JSONTools.to_string(data)
print(content)
# string 转 json
print(JSONTools.to_json(content))
# json 写入文件
JSONTools.to_file(data, 'test.json', indent=4)
# 从文件读取 json
print(JSONTools.from_file('test.json'))
✏ 总结
在使用json模块的时候,总是将方法搞混,分不清dumps
和dump
哪个是数据操作,哪个是文件操作的,同样的也分不清dumps
和loads
哪个是json数据转字符串,哪个是字符串转json的。总结以下,四个方法中,带s
的是操作字符串的,load
由加载的意思,可以理解成加载json数据,dump
则是反义,就可以知道是转字符串的了,记住四个方法的特点,就不会搞混了。