python - 在不从“列表”派生的情况下精简 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
.
解决方案
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": []
}
通过这种方式,您可以将对象结构和序列化的关注点分开。
推荐阅读
- python - celery 弦回调 on_error 缺少参数
- android - Google 的 Text To Speech 可用 Voices(葡萄牙语)
- zapier - Zapier CLI,在 inputFields 上使用选项在创建新 Zap 时不会在表单中显示
- gradle - `implementation` 而不是 `compile` for `fileTree` 会干扰复制库任务
- node.js - 如何从 json 读取 javascript 函数
- google-maps - 如何显示从最终用户位置到存储的大致位置?
- node.js - 如何编写自动更改节点版本的 .nvmrc 文件
- javascript - 脚本标签内带有占位符的淘汰赛绑定
- android - 为什么 Recyclerview 适配器 onBindViewHolder 被多次调用?
- asp.net - ASP.NET:模型验证错误 - 错误请求