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')]]
posted @ 2023-02-03 17:58  最冷不过冬夜  阅读(392)  评论(0编辑  收藏  举报