从Python 3.5中的JSON初始化类时,如何减少样板? [英] How to reduce boilerplate when initializating classes from JSONs in Python 3.5?

查看:117
本文介绍了从Python 3.5中的JSON初始化类时,如何减少样板?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一组python网络服务,可以处理通过JSON POST获得的数据对象.在我的旧服务中,我有很多样板可用于(反)序列化和检查每个对象的JSON.使用Python 3.5进行新的输入并 PEP 484 我的感觉可以大大降低.这值得么?有人对此有好的解决方案吗?

I have a set of python webservices that work with data objects they get via a JSON POSTs. In my old services I have a lot of boilerplate to (de)serialize and check JSONs for each object. With Python 3.5s new typing and PEP 484 I have the feeling that could be substantially reduced. Is it worth it? Does anyone have a good solution for it?

其他信息

我的旧样板对于每个对象都是这样的:

My old boilerplate looks like this for every object:

class Data:

    class Nested1:
        def __init__(self, nested1_flat1):
            self.nested1_flat1 = nested1_flat1

        @classmethod
        def from_jsond(cls, jsond):
            # jsond : dict of strings, lists and dicts as usually receivied from reading JSON
            kwargs = {}
            for key, val in jsond.items():
                # lots of code to deal with special objects , e.g.
                if key=='date' : kwargs[key] = cleverly_build_datetime_from_js_format(val)
            return cls.__init__(**kwargs)

    def __init__(self, flat1, nested1):
        self.flat1 = flat1
        self.nested1 = nested1

    @classmethod
    def from_jsond(cls, jsond):
        kwargs = {}
        for key, val in jsond.items():
            # lots of code to deal with nested and special objects, e.g.
            if key=='nested1' : kwargs[key] = Nested1.from_jsond(val)
        return cls.__init__(**kwargs)

我设法将其简化为以下

@from_jsond
class Data:

    @from_jsond
    class Nested1:

        @auto_assign
        @beartype
        def __init__(self, nested1_flat1: str):
            pass

    @auto_assign
    @beartype
    def __init__(self, flat1: str, nested1: Nested1)
        pass

在这里,我为 @auto_assign

Here I used snippets for @auto_assign and @beartype and my own from_jsond.

import inspect
from typing import Any

_JSON_READABLE = [str, list, dict, Any]

def _from_jsond(cls, json_dict):
    '''
    Entity specific conversion of string dictionary to entity.
    The json_dict is a dict of string, lists and other dicts as typically encoded in a JSON.
    '''
    kwargs = {}
    init_parameters = inspect.signature(cls.__init__).parameters
    for key, val in json_dict.items():
        if key in init_parameters.keys():
            if init_parameters[key].annotation in _JSON_READABLE:
                kwargs[key] = val
            else:
                if hasattr(init_parameters[key].annotation, 'from_jsond'):
                    kwargs[key] = init_parameters[key].annotation.from_jsond(val)
                else:
                    raise TypeError('No method to unserialize type "' + init_parameters[key].annotation.__name__ +  '"')
        else:
            raise AttributeError('Class "' + cls.__name__   + '" does not accept attribute "' + key + '"')
    return cls(**kwargs)

def from_jsond(cls):
    ''' Wrapper to add _from_jsonlike to cls as classmethod '''

    cls.from_jsonlike = classmethod(_from_jsond)
    return cls

有了继承,人们很可能会进一步减少继承,但是我不知道这是否值得麻烦和稳定.欢迎意见和经验:)

With inheritance one could most likely reduce it even further, but I don't know if it is all worth the hassle and stable enough. Opinions and experiences are welcome :)

推荐答案

不,PEP 484和类型提示通常不会帮助您减少样板.

No, PEP 484 and type hints in general will not help you reduce the boilerplate.

最简单的解释是python运行时不知道PEP 484. Python解释器执行类型提示只是为了确保语法正确,没有未定义的名称,等等.

The simplest explanation is that python run-time is not aware of PEP 484. Python interpreter executes type hints only to make sure the syntax is correct, there are no undefined names, etc.

因此,无法使用类型提示来有意义地更改程序的运行时行为.

Therefore, there is no way to meaningfully change the run-time behavior of your program by using type hints.

在执行解释程序之前,类型提示仅在单独的阶段中进行处理,以验证类型是否正确.没有信息从该分析流向python解释器.

Type hints are only processed in a separate phase, before you execute the interpreter, to verify that your types are correct. No information flows from that analysis to the python interpreter.

当然,您可以在运行时自行阅读源代码的类型注释,然后对它们进行所需的处理.但这显然不是您要的,因为要使用该方法做任何有用的事情,您必须编写很多相当复杂的代码.

Of course you can read type annotations for your source code in run-time yourself, and then do what you want with them. But that's clearly not what you're asking, since in order to do anything useful with that approach, you'd have to write a lot of rather complex code.

这篇关于从Python 3.5中的JSON初始化类时,如何减少样板?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆