JSON 文件操作:Python 中最好的 JSON 数据持久化工具

🍀 前言

博客地址:

👋 简介

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模块的时候,总是将方法搞混,分不清dumpsdump哪个是数据操作,哪个是文件操作的,同样的也分不清dumpsloads哪个是json数据转字符串,哪个是字符串转json的。总结以下,四个方法中,带s的是操作字符串的,load由加载的意思,可以理解成加载json数据,dump则是反义,就可以知道是转字符串的了,记住四个方法的特点,就不会搞混了。

💖 欢迎关注我的公众号

在这里插入图片描述

  • 69
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值