将Python的json.loads()object_hook参数化为工厂方法

时间:2014-07-28 05:44:59

标签: python json class object

我目前正在编写一个使用python的JSON模块的应用程序,并认为将JSON数据复活到适当的python对象会很不错。

以下作品完美无缺。

Class MyClass :
    def __init__(self, argA = None, argB = None, ... , JSON_Object=None):
        self.attrA = argA
        self.attrB = argB
        ...

        if JSON_Object :
            self.attrA = json.loads(JSON_Object, object_hook=self._getAttributeA)
            self.attrB = json.loads(JSON_Object, object_hook=self._getAttributeB)
            ...

    # Individual call back functions for the init... *yucky*.
    def _getAttributeA(self, JSON_Object) :
        if 'attrA' in JSON_Object :
            return JSON_Object['attrA']

    def _getAttributeB(self, JSON_Object) :
        if 'attrB' in JSON_Object :
            return JSON_Object['attrB']

    ...

在五个或更多属性之后,这会让每个属性重写函数变得有点烦人。考虑到这是工厂方法的理想选择,唯一需要的是参数。

我如何模拟这个?

我多次浏览了json documentation for python,并且很沮丧为什么这个功能不会立即变得微不足道。

Class MyClass :
    def __init__(self, argA=None, argB=None, ..., JSON_Object=None):
        self.attrA = argA
        self.attrB = argB
        ...

        if JSON_Object :
            self.attrA = json.loads(JSON_Object, object_hook=self._getAttribute, args=["attrA"])
            self.attrB = json.loads(JSON_Object, object_hook=self._getAttribute, args=["arrtB"])
            ...

    # super simple, general, parameterized callback function for json.loads()
    def _getAttribute(self, JSON_Object, args) :
        if args[0] in JSON_Object :
            return JSON_Object[args[0]]

一个非平凡的解决方案很好,但更大的问题是为什么这不能立即实现?

1 个答案:

答案 0 :(得分:0)

你选择了一种非常奇怪的方式来使用object_hookobject_hook用于自定义反序列化过程以将dicts转换为其他一些数据类型,而不是用于从JSON中读取字段。如果你只想阅读字段,你应该loads没有object_hook的JSON,然后使用普通的索引语法读取生成的字典中的字段:

data = json.loads(JSON_Object)
self.attrA = data['attrA']
self.attrB = data['attrB']
...

或者如果要将所有字段转储到对象的同名属性中:

self.__dict__.update(json.loads(JSON_Object))

如果您想以递归方式应用该将是使用object_hook的好时机:

class JSON_Namespace(object):
    def __init__(self, data_dict):
        self.__dict__.update(data_dict)
    @classmethod
    def load_from_json(cls, json_string):
        return json.loads(json_string, object_hook=cls)