简体   繁体   English

如何使用Python的JSONDecoder?

[英]How to use Python's JSONDecoder?

For the life of me I haven't been able to find any example of this for Python.对于 Python,我一直没能找到任何这样的例子。

Say I have a class Person, and I want to serialize and deserialize an object from that class.假设我有一个 class 人,我想从 class 序列化和反序列化一个 object。

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))

Now, I want to serialize that nice Person object, and I want to support datetime objects.现在,我想序列化那个好人object,我想支持datetime对象。 So I wrote a custom serializer:所以我写了一个自定义序列化程序:

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)

The purpose is to be able to support a couple of types, including datetime .目的是能够支持几种类型,包括datetime

Now comes the time to deserialize.现在是反序列化的时候了。 I had to write a custome deserializer to match the serializer.我必须编写一个自定义反序列化程序来匹配序列化程序。 Here it is:这里是:

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"])

If I trigger:如果我触发:

coder = JSONCoder()
s = coder.encode(p1.__dict__)
print("Encoded: " + s)

dcoder = JSONDCoder()
d = dcoder.decode(s)
print("Decoded: " + str(d))

I obtain the following output:我获得以下 output:

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

The only way to obtain anything apart from None , is to modify the decoder and change it to:获得除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

Whatever other option makes it to return None , as shown above.无论其他选项如何返回None ,如上所示。

How can I have my custom decoder so it supports datetime types?我怎样才能让我的自定义解码器支持日期时间类型?

You simply forgot to add a return statement at the end of the from_dict method.您只是忘记在 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

This definition should work, the output for me is the following:这个定义应该有效,对我来说 output 如下:

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)}

Let me know if it was what you were looking for.让我知道这是否是您要找的东西。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM