代码之家  ›  专栏  ›  技术社区  ›  Baltasarq

如何使用Python的JSONDecoder?

  •  0
  • Baltasarq  · 技术社区  · 4 年前

    在我的一生中,我还没有找到任何Python的例子。

    假设我有一个类Person,我想序列化和反序列化该类中的一个对象。

    class Person:
        def __init__(self, n, b):
            self._name = n
            self._born = b
    
        @property
        def name(self):
            return self._name
    
        @property
        def born(self):
            return self._born
    
        def __str__(self):
            return f"{self.name} was born in {self.born.isoformat()}"
    
    p1 = Person("Baltasar", datetime(1919, 7, 1))
    
    

    现在,我想把这个美好的故事系列化 反对,我想支持 约会时间 物体。所以我写了一个自定义序列化程序:

    class JSONCoder(json.JSONEncoder):
        def default(self, obj):
            if isinstance(obj, datetime):
                return { "__class__": "datetime",
                         "y": obj.year,
                         "month": obj.month,
                         "d": obj.day,
                         "h": obj.hour,
                         "minute": obj.minute,
                         "s": obj.second }
    
            return json.JSONEncoder.default(self, obj)
    

    其目的是能够支持多种类型,包括 约会时间 .

    现在是反序列化的时候了。我必须编写一个自定义反序列化程序来匹配序列化程序。这是:

    class JSONDCoder(json.JSONDecoder):
        def __init__(self):
            json.JSONDecoder.__init__(self, object_hook=JSONDCoder.from_dict)
    
        @staticmethod
        def from_dict(d):
            if d.get("__class__") == "datetime":
                return datetime(d["y"], d["month"], d["d"],
                                d["h"], d["minute"], d["s"])
    

    如果我触发:

    coder = JSONCoder()
    s = coder.encode(p1.__dict__)
    print("Encoded: " + s)
    
    dcoder = JSONDCoder()
    d = dcoder.decode(s)
    print("Decoded: " + str(d))
    

    我获得以下输出:

    Encoded: {"_name": "Baltasar", "_born": {"__class__": "datetime", "y": 1919, "month": 7, "d": 0, "h": 0, "minute": 0, "s": 0}}
    Decoded: None
    ...
    

    获得任何东西的唯一途径除了 没有一个 ,是修改解码器并将其更改为:

    class JSONDCoder(json.JSONDecoder):
        def __init__(self):
            json.JSONDecoder.__init__(self, object_hook=JSONDCoder.from_dict)
    
        @staticmethod
        def from_dict(d):
            if d.get("__class__") == "datetime":
                return d
    

    不管还有什么选择,它都会回来 没有一个 ,如上所示。

    如何让我的自定义解码器支持 约会时间 类型?

    1 回复  |  直到 4 年前
        1
  •  1
  •   GiacomoM    4 年前

    您只是忘记了在from_dict方法的末尾添加return语句。

    class JSONDCoder(json.JSONDecoder):
    def __init__(self):
        json.JSONDecoder.__init__(self, object_hook=JSONDCoder.from_dict)
    
    @staticmethod
    def from_dict(d):
        if d.get("__class__") == "datetime":
            return datetime(d["y"], d["month"], d["d"],
                            d["h"], d["minute"], d["s"])
        return d
    

    这个定义应该有效,我的输出如下:

    Encoded: {"_name": "Baltasar", "_born": {"__class__": "datetime", "y": 1919, "month": 7, "d": 1, "h": 0, "minute": 0, "s": 0}}
    Decoded: {'_name': 'Baltasar', '_born': datetime.datetime(1919, 7, 1, 0, 0)}
    

    让我知道这是不是你想要的。