我可以让 json.dumps/loads 使用 Encoder/Decoder 个实例而不是 类 吗?
Can I make json.dumps/loads work with Encoder/Decoder instances instead of classes?
请考虑这个自定义 JSON-编码器的玩具示例。
import json
from typing import Any
class MyNumber:
def __init__(self, num):
self.num = num
class MultEncoder(json.JSONEncoder):
'Multiply MyNumber instances when JSON-encoding.'
def default(self, o: Any) -> Any:
if isinstance(o, MyNumber):
return o.num*2
return super().default(o)
它是这样工作的:
>>> json.dumps({"a": MyNumber(5)}, cls=MultEncoder)
'{"a": 10}'
我的问题是如何使因子动态化?我想做:
class MultEncoder(json.JSONEncoder):
'Multiply MyNumber instances when JSON-encoding.'
def __init__(self, factor, *args, **kwargs):
self.factor = factor
super().__init__(*args, **kwargs)
def default(self, o: Any) -> Any:
if isinstance(o, MyNumber):
return o.num*self.factor
return super().default(o)
当然,json.dumps({"a": MyNumber(5)}, cls=MultEncoder(7))
失败了
TypeError: 'MultEncoder' object is not callable
因为 cls
参数应该是一个 class,而不是一个实例。
edit1:请注意,我无法编写自定义 my_json_dumps
/my_json_loads
函数,我只能控制在代码的其他部分导入哪些 encoder/decoder classes其中使用 json.dumps
和 loads
。
edit2:请注意,我试图举一个通用的简单示例。在我的真实代码中,encoder/decoder 需要知道连接到数据库和其他动态配置的凭据。
我想出了一个非常丑陋的解决方案:一个 class-factory 函数,其中返回的 class 访问 closure-variables.
def MultEncoder(factor):
class _MultEncoder(json.JSONEncoder):
'Multiply MyNumber instances when JSON-encoding.'
def default(self, o: Any) -> Any:
if isinstance(o, MyNumber):
return o.num*factor
return super().default(o)
return _MultEncoder
演示:
>>> json.dumps({"a": MyNumber(5)}, cls=MultEncoder(7))
'{"a": 35}'
这是我们在这里能做的最好的吗?
只需添加 __call__
方法即可使 MultEncoder
class 实例可调用。
class MyNumber:
def __init__(self, num):
self.num = num
class MultEncoder(json.JSONEncoder):
'Multiply MyNumber instances when JSON-encoding.'
def __init__(self, factor, *args, **kwargs):
self.factor = factor
super().__init__(*args, **kwargs)
def __call__(self,**kwargs):
return self
def default(self, o: Any) -> Any:
if isinstance(o, MyNumber):
return o.num*self.factor
return super().default(o)
json.dumps({"a": MyNumber(5)}, cls=MultEncoder(7))
输出为:
'{"a": 35}'
请考虑这个自定义 JSON-编码器的玩具示例。
import json
from typing import Any
class MyNumber:
def __init__(self, num):
self.num = num
class MultEncoder(json.JSONEncoder):
'Multiply MyNumber instances when JSON-encoding.'
def default(self, o: Any) -> Any:
if isinstance(o, MyNumber):
return o.num*2
return super().default(o)
它是这样工作的:
>>> json.dumps({"a": MyNumber(5)}, cls=MultEncoder)
'{"a": 10}'
我的问题是如何使因子动态化?我想做:
class MultEncoder(json.JSONEncoder):
'Multiply MyNumber instances when JSON-encoding.'
def __init__(self, factor, *args, **kwargs):
self.factor = factor
super().__init__(*args, **kwargs)
def default(self, o: Any) -> Any:
if isinstance(o, MyNumber):
return o.num*self.factor
return super().default(o)
当然,json.dumps({"a": MyNumber(5)}, cls=MultEncoder(7))
失败了
TypeError: 'MultEncoder' object is not callable
因为 cls
参数应该是一个 class,而不是一个实例。
edit1:请注意,我无法编写自定义 my_json_dumps
/my_json_loads
函数,我只能控制在代码的其他部分导入哪些 encoder/decoder classes其中使用 json.dumps
和 loads
。
edit2:请注意,我试图举一个通用的简单示例。在我的真实代码中,encoder/decoder 需要知道连接到数据库和其他动态配置的凭据。
我想出了一个非常丑陋的解决方案:一个 class-factory 函数,其中返回的 class 访问 closure-variables.
def MultEncoder(factor):
class _MultEncoder(json.JSONEncoder):
'Multiply MyNumber instances when JSON-encoding.'
def default(self, o: Any) -> Any:
if isinstance(o, MyNumber):
return o.num*factor
return super().default(o)
return _MultEncoder
演示:
>>> json.dumps({"a": MyNumber(5)}, cls=MultEncoder(7))
'{"a": 35}'
这是我们在这里能做的最好的吗?
只需添加 __call__
方法即可使 MultEncoder
class 实例可调用。
class MyNumber:
def __init__(self, num):
self.num = num
class MultEncoder(json.JSONEncoder):
'Multiply MyNumber instances when JSON-encoding.'
def __init__(self, factor, *args, **kwargs):
self.factor = factor
super().__init__(*args, **kwargs)
def __call__(self,**kwargs):
return self
def default(self, o: Any) -> Any:
if isinstance(o, MyNumber):
return o.num*self.factor
return super().default(o)
json.dumps({"a": MyNumber(5)}, cls=MultEncoder(7))
输出为:
'{"a": 35}'