如何使用Python的JSONDecoder?
How to use Python's JSONDecoder?
我一直没能找到 Python 的任何例子。
假设我有一个 class 人,我想序列化和反序列化那个 class 的对象。
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))
现在,我想序列化那个漂亮的 Person 对象,并且我想支持 datetime 对象。所以我写了一个自定义序列化程序:
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)
目的是能够支持多种类型,包括 datetime。
现在是反序列化的时候了。我必须编写一个自定义反序列化程序来匹配序列化程序。这是:
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
...
除了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
无论其他选项如何成为 return None,如上所示。
如何让我的自定义解码器支持 datetime 类型?
您只是忘记在 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)}
让我知道这是否是您要找的。
我一直没能找到 Python 的任何例子。
假设我有一个 class 人,我想序列化和反序列化那个 class 的对象。
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))
现在,我想序列化那个漂亮的 Person 对象,并且我想支持 datetime 对象。所以我写了一个自定义序列化程序:
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)
目的是能够支持多种类型,包括 datetime。
现在是反序列化的时候了。我必须编写一个自定义反序列化程序来匹配序列化程序。这是:
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
...
除了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
无论其他选项如何成为 return None,如上所示。
如何让我的自定义解码器支持 datetime 类型?
您只是忘记在 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)}
让我知道这是否是您要找的。