python对json文件封装处理
为了解决json文件处理需求,更方便的读写json文件,对其进行增删改查操作,利用json库及eval,
exec函数特性,封装成工具类,记录个人学习心得。
- demo.json
{
"name": "BeJson",
"url": "http://www.bejson.com",
"page": 88,
"isNonProfit": true,
"address": {
"street": "科技园路.",
"city": "江苏苏州",
"country": "中国"
},
"links": [
{
"name": "Google",
"url": "http://www.google.com"
},
{
"name": "Baidu",
"url": "http://www.baidu.com"
},
{
"name": "SoSo",
"url": "http://www.SoSo.com"
}
]
}
- JsonTool.py
import json
from typing import List, Dict, Any
class JsonTool:
""" json文件 封装工具"""
def __init__(self):
self.fp = None
self.load_dict = None
def _key_join(self, key_list: List) -> str:
""" key数据拼接 """
temp = "self.load_dict"
for _, key in enumerate(key_list):
if ":" in key:
kv = key.split(":")[0]
index = int(key.split(":")[1])
temp += f'[{index}]["{kv}"]'
else:
temp += f'["{key}"]'
return temp
def read_file(self, file=None) -> Dict:
"""
读取json文件,返回 python字典数据
:return:
"""
self.fp = file
if not self.fp:
raise Exception("未指定文件路径")
try:
with open(self.fp, 'r', encoding='utf-8') as load_f:
self.load_dict = json.load(load_f)
# format_load_dict = json.dumps(self.load_dict, indent=4, separators=(',', ':')
# ensure_ascii=False) # ,sort_keys=True
# print('read_file:\n', format_load_dict)
return self.load_dict
except ValueError as err:
print(f"{self.fp}json文件读取失败或格式有误:{err}")
def write_file(self, file=None) -> None:
"""
json文件变更操作后,回写入文件
:return:
"""
if not file:
file = self.fp
with open(file, 'w', encoding='utf-8') as write_f:
json.dump(self.load_dict, write_f, indent=4,
ensure_ascii=False) # , separators=(',', ':')
def validateJSON(self, path=None) -> bool:
"""
校验json文件是否正确
:return: True/False
"""
try:
with open(path, 'r', encoding='utf-8') as load_f:
self.load_dict = json.load(load_f)
except ValueError as err:
print(f"{self.fp}json文件读取失败或格式有误:{err}")
return False
return True
def get_values(self, key_list: List) -> List:
"""
从嵌套的json数据中获取指定key的所有值.
example: get_values(["links", "url"])
:key_list: 一级一级嵌套的List
:return: json-value
"""
temp = self._key_join(key_list[:-1])
dataList = [item.get(key_list[-1]) for item in eval(temp)]
return dataList
def get_value(self, key_list: List) -> Any:
"""
从嵌套的json数据中获取对应一个key的值
example: get_value(["page"]), get_value(["links", "name:0"])
:key_list: 一级一级嵌套的List
:return: json-value
"""
# print(f"{self._key_join(key_list[-1])=}")
# print(f"{eval(self._key_join(key_list[-1]))=}")
if len(key_list) > 1 and len(eval(self._key_join(key_list[:-1]))) >= 2 and ":" not in key_list[-1]:
raise Exception("指定key存在多个,请指定下标")
temp = self._key_join(key_list)
return eval(temp)
def set_value(self, key_list: List, value: Any = "None") -> None:
"""
从嵌套的json数据中设置或者添加值
example: set_value(["address", "house"], "大别野")
:key_list: 一级一级嵌套的List
:return:
"""
temp = self._key_join(key_list)
if isinstance(value, str):
result = temp + f'="{value}"' # eval函数不能执行赋值操作, 使用另一个强大的函数exec
elif isinstance(value, int) or isinstance(value, bool):
result = temp + f'={value}'
elif isinstance(value, list) or isinstance(value, tuple):
result = temp + f'={value}'
exec(result)
def remove_key(self, key_list):
""" 移除 json指定字段数据 """
temp = "del " + self._key_join(key_list)
exec(temp)
if __name__ == '__main__':
config = JsonTool()
if config.validateJSON("./demo.json"):
config.read_file("./demo.json")
print(f"config.load_dict_0: {config.load_dict}")
# config.get_value(["links", "name"]) # X
n_v1 = config.get_value(["links", "name:0"])
n_v2 = config.get_value(["links", "name:1"])
n_v3 = config.get_value(["page"])
n_v4 = config.get_value(["isNonProfit"])
print(f"n_v1: {n_v1}, n_v2: {n_v2}, n_v3: {n_v3}, n_v4: {n_v4}")
config.set_value(["links", "name:2"], "Souhu")
config.set_value(["isNonProfit"], False)
config.set_value(["page"], 90)
print(f"config.load_dict_1: {config.load_dict}")
link = [
{
"name": "Google",
"url": "http://www.google.com"
},
{
"name": "Baidu",
"url": "http://www.baidu.com"
}
]
config.set_value(["links"], link)
config.set_value(["address", "house"], "大别野")
config.remove_key(["address", "street"]) # 科技园路.
print(f"config.load_dict_2: {config.load_dict}")
config.write_file("./res.json")
n_v5 = config.get_values(["links", "url"])
print(f"n_v4: {n_v5}")