python-json的自定义编码器与自定义解码器
json的数据类型有限,在实际业务中可能会遇到数据无法使用JSON编码的问题。如果我们需要转发的数据有大量或位置不规则的json无法解析数据类型时,事先处理就变成了一件比较麻烦的事。这里可以使用json模块的编码器和解码器来解决这个问题。
自定义编码器
import json
from decimal import Decimal
from datetime import datetime
# json扩展编码器
class MyJsonEncoder(json.JSONEncoder):
def default(self, field):
"""
:param field: 原始的数据
:return: 处理后的数据
"""
if isinstance(field, datetime):
return field.strftime('%Y-%m-%d %H:%M:%S')
elif isinstance(field, Decimal):
return str(field)
else:
return json.JSONEncoder.default(self, field)
info = [Decimal("1"), datetime.now(), {"decimal": Decimal("2"), "datetime": datetime.now()}]
print(json.dumps(info, cls=MyJsonEncoder)) # cls -> 指定JSON编码器
==>
["1", "2023-02-03 16:48:29", {"decimal": "2", "datetime": "2023-02-03 16:48:29"}]
自定义解码器
# json自定义解码器
class MyJsonDecoder(json.JSONDecoder):
def __init__(self, *args, **kwargs):
super().__init__(
object_hook=self.object_hook,
parse_float=self.parse_float,
parse_int=self.parse_int,
parse_constant=self.parse_constant,
# object_pairs_hook=self.object_pairs_hook,
*args, **kwargs)
def object_hook(self, o):
"""
对字典解码,如果同时设置'object_pairs_hook','object_hook'将不生效
:param o: 原始数据字典
:return: 实际需要的数据
"""
return o
def parse_float(self, o):
"""
对浮点型解码
:param o: 原始浮点型
:return: 实际需要的数据
"""
return o
def parse_int(self, o):
"""
对整型解码
:param o: 原始整型
:return: 实际需要的数据
"""
return o
def parse_constant(self, o):
"""
对于'-Infinity', 'Infinity', 'NaN'之类的特殊值进行解码
:param o:
:return:
"""
return o
def object_pairs_hook(self, o):
"""
对有序列表解码,如果同时设置'object_hook','object_hook'将不生效
:param o: 原始数据数据
:return: 实际需要的数据
"""
return o
info = '[1, "2023-02-03 16:48:29", {"decimal": "2.2", "datetime": "2023-02-03 16:48:29"}, [3, "4"]]'
print(json.loads(info, cls=MyJsonDecoder))
==>
['1', '2023-02-03 16:48:29', {'decimal': '2.2', 'datetime': '2023-02-03 16:48:29'}, ['3', '4']]
实际举例-支持decimal格式数据
import json
from decimal import Decimal
# json自定义编码器
class MyJsonEncoder(json.JSONEncoder):
def default(self, field):
if isinstance(field, Decimal):
return {"__class__": "Decimal", "value": str(field)}
else:
return json.JSONEncoder.default(self, field)
# json自定义解码器
class MyJsonDecoder(json.JSONDecoder):
def __init__(self, *args, **kwargs):
super().__init__(object_hook=self.object_hook, *args, **kwargs)
def object_hook(self, o):
if o.get('__class__') == "Decimal":
return Decimal(o.get('value', 0))
return o
info = [Decimal("1"), Decimal("1.1"),
{"decimal1": Decimal("2.1"), "decimal2": Decimal("2.2")},
[Decimal("3.1"), Decimal("3.2")]]
info1 = json.dumps(info, cls=MyJsonEncoder)
info2 = json.loads(info1, cls=MyJsonDecoder)
print(info1, end="\n\n")
print(info2)
==>
[{"__class__": "Decimal", "value": "1"}, {"__class__": "Decimal", "value": "1.1"}, {"decimal1": {"__class__": "Decimal", "value": "2.1"}, "decimal2": {"__class__": "Decimal", "value": "2.2"}}, [{"__class__": "Decimal", "value": "3.1"}, {"__class__": "Decimal", "value": "3.2"}]]
[Decimal('1'), Decimal('1.1'), {'decimal1': Decimal('2.1'), 'decimal2': Decimal('2.2')}, [Decimal('3.1'), Decimal('3.2')]]