python - 用JSON数据包装python类,哪个更好?

标签 python json class wrapper api-design

序言:我正在针对交付json的服务编写python api。
文件以json格式存储在磁盘上以缓存值。
API应该对JSON数据进行类访问,因此IDE和用户可以在运行前知道对象中有什么(只读)属性,同时也提供一些便利功能。
问:我有两种可能的实现方式,我想知道哪一个更好或“Python”。虽然我两者都喜欢,但如果你能想出更好的解决方案,我愿意提出建议。
第一个解决方案:定义和继承JSONWRAPPER,同时很好,它是冗长的和重复的。

class JsonDataWrapper:
    def __init__(self, json_data):
        self._data = json_data

    def get(self, name):
        return self._data[name]


class Course(JsonDataWrapper):
    def __init__(self, data):
        super().__init__(data)
        self._users = {}  # class omitted
        self._groups = {}  # class omitted
        self._assignments = {}

    @property
    def id(self): return self.get('id')

    @property
    def name(self): return self.get('full_name')

    @property
    def short_name(self): return self.get('short_name')

    @property
    def users(self): return self._users

    @users.setter
    def users(self, data):
        users = [User(u) for u in data]
        for user in users:
            self.users[user.id] = user
            # self.groups = user  # this does not make much sense without the rest of the code (It works, but that decision will be revised :D)

第二种解决方案:使用lambda来缩短语法。在短时间工作时,它看起来不太合适(见下面的edit1)。
def json(name): return property(lambda self: self.get(name))

class Group(JsonDataWrapper):
    def __init__(self, data):
        super().__init__(data)
        self.group_members = []  # elements are of type(User). edit1, was self.members = []

    id = json('id')
    description = json('description')
    name = json('name')
    description_format = json('description_format')

(命名这个函数‘JSON’不是问题,因为我不在其中导入JSON)。
我有一个可能的第三个解决方案,我不能把我的头绕过来:重写属性Buffin,这样我就可以定义一个装饰器来封装返回的字段名用于查找:
@json  # just like a property fget
def short_name(self): return 'short_name'

如果代码更好的话,可能会有点短。
不合格解决方案(IMHO):
JSON {de,En}编码器:杀死所有灵活性,不提供只读属性的手段
__{get,set}attr__:在运行前无法确定属性。虽然它可以将self.get('id')缩短为self['id']它也会使底层json数据中没有属性的情况更加复杂。
谢谢你的阅读!
编辑1:2016-07-20t08:26z
为了进一步澄清(@supersaiyan)为什么我不太喜欢第二个解决方案:
我觉得lambda函数与其他类语义完全断开了连接(这也是为什么它更短的原因:d)。我想我可以通过在代码中正确地记录决策来帮助自己更喜欢它。第一种解决方案对于每个理解@property含义的人来说都很容易理解,而不需要任何额外的解释。
关于@supersaiyan的第二点评论:你的问题是,为什么我把Group.members作为属性放在这里?列表存储类型(用户)实体,可能不是您想象的那样,我更改了示例。
JWODDER:下次我会用代码复查,不知道那是一件事。
(另外:我真的认为Group.members让你们中的一些人失望了,我编辑了代码使其更明显:组成员是将被添加到列表中的用户。
The complete code is on github,虽然没有记录,但对某些人来说可能很有趣。记住:这都是WIP:d)

最佳答案

你考虑过使用元类吗?

class JsonDataWrapper(object):
    def __init__(self, json_data):
        self._data = json_data

    def get(self, name):
        return self._data[name]

class JsonDataWrapperMeta(type):
    def __init__(self, name, base, dict):
        for mbr in self.members:
            prop = property(lambda self: self.get(mbr))
            setattr(self, mbr, prop)

# You can use the metaclass inside a class block
class Group(JsonDataWrapper):
    __metaclass__ = JsonDataWrapperMeta
    members = ['id', 'description', 'name', 'description_format']

# Or more programmatically
def jsonDataFactory(name, members):
    d = {"members":members}
    return JsonDataWrapperMeta(name, (JsonDataWrapper,), d)

Course = jsonDataFactory("Course", ["id", "name", "short_name"])

关于python - 用JSON数据包装python类,哪个更好?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38464302/

相关文章:

javascript - ExtJS 4 - 从动画监听器调用 javascript 类方法失败

VB.NET 设计器错误 : How to (correctly) inherit form that inherits form?

python - 在给定索引的列表列表中查找最大值的列表并返回其第一个值

python - 如何优化此 Python 代码以使其运行得更快?

python - Django 中的 "app"是什么?

android - 在 Android 中将 POJO 转换为 JSON Retrofit

javascript - 从 JavaScript 访问 JSON 元素

jquery - 使用 jsonpath 进行字符串搜索

python - 使用 numpy 实现基于欧氏距离的公式

java - 可编辑的二维数组