【问题标题】:Slimming JSON messages down without deriving from `list`在不从“列表”派生的情况下精简 JSON 消息
【发布时间】:2020-02-08 20:57:50
【问题描述】:

考虑一个为待办事项列表生成 JSON 消息的服务器。

import json

class Action(object):
    def __init__(self, what, when):
        self.what = what
        self.when = when

class Actions(object):
    def __init__(self):
        self.actions = []

    def insert(self, action):
        self.actions.append({'action': 'insert_todo',
                             'detail': {'what': action.what,
                                        'when': action.when}})

class Batch(object):
    def __init__(self):
        self.urgent_actions = Actions()
        self.ordinary_actions = Actions()
        self.urgent_actions.insert(Action('tidy up', '8am'))

def jdefault(o):
    return o.__dict__

def output_json():
    batch = Batch()
    mystr = json.dumps(batch,
                       default=jdefault,
                       indent=4)
    print(mystr)

output_json()

这很好,我们得到了消息:

{
    "urgent_actions": {
        "actions": [
            {
                "action": "insert_todo",
                "detail": {
                    "what": "tidy up",
                    "when": "8am"
                }
            }
        ]
    },
    "ordinary_actions": {
        "actions": []
    }
}

但是在操作的优先级和每条消息中重复 actions 要求进行一些清理。

我们可以通过从list 派生Actions 来做到这一点:

class Actions(list):
    def __init__(self, *args):
        list.__init__(self, *args)

    def insert(self, action):
        self.append({'action': 'insert_todo',
                     'detail': {'what': action.what,
                                'when': action.when}})

我们确实得到了更精简的 JSON 消息:

{
    "urgent_actions": [
        {
            "action": "insert_todo",
            "detail": {
                "what": "8am",
                "when": "8am"
            }
        }
    ],
    "ordinary_actions": []
}

然而, deriving from list is far from 最好的主意。

如果不从list 派生,您会使用什么其他(惯用的)方式来获取更精简的消息?

消息将通过 Flask 发送,以防您还想批评 json.dumps 的使用。

【问题讨论】:

  • 制作一个动作列表,其中一些(或全部)具有布尔“紧急”属性?
  • @Tomalak 我们可以按照您的建议完全摆脱Batch。这里的“紧急属性”是特征的占位符。这是与Actions 不同的问题。避免从list 继承可能是个好主意?

标签: python json flask server


【解决方案1】:

您可以将定义 json 的结构委托给 jdefault 函数,而不是更改类。

def jdefault(o):
    if isinstance(o, Batch):
        return o.__dict__
    if isinstance(o, Actions):
        return o.actions
    raise TypeError("Object of type {} is not JSON serializable".format(type(o)))

生成所需的输出:

{
    "urgent_actions": [
        {
            "action": "insert_todo",
            "detail": {
                "what": "tidy up",
                "when": "8am"
            }
        }
    ],
    "ordinary_actions": []
}

这样您就可以将对象结构和序列化的关注点分开。

【讨论】:

    猜你喜欢
    • 2015-03-12
    • 2018-06-13
    • 2018-12-30
    • 2011-11-22
    • 1970-01-01
    • 2019-10-04
    • 2023-03-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多