首页 > 解决方案 > 在不从“列表”派生的情况下精简 JSON 消息

问题描述

考虑一个为待办事项列表生成 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是要求进行一些清理。

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

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": []
}

然而, 列表派生 不是最好 主意。

你会用什么其他(惯用的)方式来获得更苗条的信息,而不是从list?

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

标签: pythonjsonflaskserver

解决方案


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

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": []
}

通过这种方式,您可以将对象结构和序列化的关注点分开。


推荐阅读