python - 如何创建一个动态的嵌套 json,可以在之后存储和重新加载和编辑?
问题描述
我想提供以后可以由用户编辑的模板。因此,它应该是人类可读的 .json 对象。
仅包含一个字段的模板示例:
{"template_name": "sample_name",
"attribute_fields":
[{"attribute_name": "banana",
"attribute_tags": ["chiquita", "pinkylady"],
"attribute_numbers": [[1, 2, 3, 4] [5, 6, 7, 8]]}]
}
我想动态扩展这个json,因为有时会添加更多的字段-所以应该有更多的“attribute_fields”
像这样:
{"template_name": "sample_name",
"attribute_fields":
[{"attribute_name": "banana",
"attribute_tags": ["chiquita", "pinkylady"],
"attribute_numbers": [[1, 2, 3, 4] [5, 6, 7, 8]]},
{attribute_name": "apple",
"attribute_tags": ["applejack", "applepie"],
"attribute_numbers": [[123, 45] [666] [5, 5, 5, 5]]}]
}
到目前为止,我已经通过创建一个空的 defaultdict 来做到这一点,
empty_template = collections.defaultdict(list)
#yes I used a list.. don't know if there would've been a better option, just tried it and sticked to it
empty_template["template_name"].append(template_name)
looks like this
{"template_name": "sample_name"}
or, printing it, it looks exactly like this:
defaultdict(<class 'list'>, {'template_name': ['sample_name']})
然后创建一个具有所有所需属性的新 defaultdict,然后将这个新的 defaultdict (new_attribute_dict) 附加到旧的 defaultdict (template_to_be_extended)。
def add_attribute_to_template:
new_attribute_dict = create_new_attribute_dict(attribute_name, attribute_tags, attribute_numbers)
template_to_be_extended["attribute_fields"].append(new_attribute_dict)
#create_new_attribute_dict looks like this:
# create empty dictionary
attribute_dict = collections.defaultdict(list)
# add all attribute properties
attribute_dict["attribute_name"] = attribute_name
... and so on
之后,我将这个扩展模板 json.dumps 并放入我的数据库中。直到这里,一切似乎都很好(但我真的认为应该有一种更漂亮的方法来实现这一点?)。
在我用 json.loads 读回它之后,我必须再次从这个 json 字符串中创建一个 defaultdict,这样我就可以附加键值对(attribute_fields)。这是所有事情都变得非常糟糕的地方,我不知道该怎么办。我这样尝试:
template_to_be_extended = collections.defaultdict(lambda: json.loads(template_persistence.get(template_name))) #template_persistence returns the file from my database
extended_template = template_creator.add_attribute_to_template(template_to_be_extended,
attribute_name, attribute_tags, attribute_numbers)
但我真的一点头绪都没有。本来以为我可以在不使用 lambda 的情况下再次获得 defaultdict,但这会引发错误(TypeError:第一个参数必须是可调用的或无) - 所以我将它设为可调用的......呃......
这样,我得到一个 AttributeError: 'dict' object has no attribute 'append',所以我也尝试从 extended_template 中创建一个 defaultdict
extended_template = collections.defaultdict(lambda: template_creator.add_attribute_to_template(template_to_be_extended,
attribute_name, attribute_tags, attribute_numbers))
错误消失了,但打印扩展模板只返回一个空的 {}。
在这个问题上停留了几个小时,现在什么也看不到。也许盯着它看太久了.. 对所有提示或其他方式来实现结果感到满意(重要的是我以后可以使用反序列化的 json 对象中的列表)。
提前致谢
卡尔萨里
解决方案
我将冒昧地重组您存储模板的方式并提出以下(示例)结构:
{
"template1": [
{
"attribute_name": "banana",
"attribute_tags": ["chiquita", "pinkylady"],
"attribute_numbers": [[1, 2, 3, 4], [5, 6, 7, 8]]
},
{
"attribute_name": "apple",
"attribute_tags": ["applejack", "applepie"],
"attribute_numbers": [[123, 45], [666], [5, 5, 5, 5]]
}
],
"template2": [
{
"attribute_name": "fwafaw",
"attribute_tags": ["fawg", "gawggwa"],
"attribute_numbers": [[22]]
},
{
"attribute_name": "vccbx",
"attribute_tags": ["vzvvxz", "wgagaw"],
"attribute_numbers": [[123, 66], [5, 5]]
}
]
}
基本上,您将模板保存在字典中,每个键代表模板名称,其中值是属性列表。
您可以使用pickle
将整个内容作为二进制文件存储在一个文件中,您可以像以前一样从中检索它,避免 JSON 序列化/反序列化。
示例代码:
import pickle
from collections import defaultdict
# initialize the templates variable
templates = defaultdict(list)
# add the first template
templates['template1'].append({
"attribute_name": "banana",
"attribute_tags": ["chiquita", "pinkylady"],
"attribute_numbers": [[1, 2, 3, 4], [5, 6, 7, 8]]
})
# store the templates data to a binary file
with open("templates.data", "wb") as pf:
pickle.dump(templates, pf)
# retrieve the templates from the binary file
with open("templates.data", "rb") as pf:
retrieved_templates = pickle.load(pf)
# let's inspect the retrieved templates, it will be exactly like the initial structure
print(retrieved_templates)
# let's append a new attribute to the template
retrieved_templates['template1'].append({
"attribute_name": "apple",
"attribute_tags": ["applejack", "applepie"],
"attribute_numbers": [[123, 45], [666], [5, 5, 5, 5]]
})
# restore the templates data
with open("templates.data", "wb") as pf:
pickle.dump(retrieved_templates, pf)
# re-retrieve the templates
with open("templates.data", "rb") as pf:
retrieved_templates_second = pickle.load(pf)
# will display with the updated attributes
print(retrieved_templates_second)
如果您要在控制台中运行它,您将拥有:
defaultdict(<class 'list'>, {'template1': [{'attribute_name': 'banana', 'attribute_tags': ['chiquita', 'pinkylady'], 'attribute_numbers': [[1, 2, 3, 4], [5, 6, 7, 8]]}]})
在那之后
defaultdict(<class 'list'>, {'template1': [{'attribute_name': 'banana', 'attribute_tags': ['chiquita', 'pinkylady'], 'attribute_numbers': [[1, 2, 3, 4], [5, 6, 7, 8]]}, {'attribute_name': 'apple', 'attribute_tags': ['applejack', 'applepie'], 'attribute_numbers': [[123, 45], [666], [5, 5, 5, 5]]}]})
此代码的目的是概述您要实现的目标,因此如果您要隐藏这些操作并将它们概括为函数和类,请尽量保持此脚本中呈现的流程。
推荐阅读
- android - 如何在本机后台服务中使用(角度)HTTP 客户端 - NativeScript
- java - 在 libgdx 游戏中将 GoogleMap 显示为片段
- python - 将循环中的数据框写入多个 Excel 文件
- gcc - 如何将 ilogb 与 newLib 一起使用?
- python - Movidius 和模板匹配
- php - Laravel api http 请求在 2 个具有不同浏览器的客户端上排序/排队
- javascript - 完成时的 AJAX 递归回调
- python - Python 中 Beautiful Soup XML 解析的问题
- http-headers - 在响应标头中隐藏 mobilefirst 7 服务器信息
- python - Reading data from /sdb1