HTML表单数据转递归JSON字典
我想把平面的表单数据转换成递归的JSON数据,使用Python或JavaScript。这种JSON数据之后可以被一个模板引擎解析(可以去谷歌搜一下tempest,它的语法跟Django类似)。虽然有很多例子可以把平面数据转换成递归数据,但问题是它不能仅仅是字典或列表。
我尝试了很多方法,但到现在还没成功。所以在思考了至少两周后,我决定在这里问问。
我的表单数据大概是这样的(键名可能会不同):
formdata = [
{"formname": "name", "formvalue": "Roel Kramer"},
{"formname": "email", "formvalue": "blaat@blaat.nl"},
{"formname": "paragraph-0.title", "formvalue": "test titel 1"},
{"formname": "paragraph-0.body", "formvalue": "bla bla body 1"},
{"formname": "paragraph-0.image-0.src", "formvalue": "src 1"},
{"formname": "paragraph-0.image-1.src", "formvalue": "src 2"},
{"formname": "paragraph-1.title", "formvalue": "test titel 2"},
{"formname": "paragraph-1.body", "formvalue": "bla bla body 2"},
{"formname": "paragraph-1.image-0.src", "formvalue": "src 3"},
{"formname": "paragraph-1.image-1.src", "formvalue": "src 4"},
{"formname": "paragraph-1.image-2.src", "formvalue": "src 5"},
{"formname": "paragraph-2.title", "formvalue": "test titel 3"},
{"formname": "paragraph-2.body", "formvalue": "bla bla body 3"},
{"formname": "paragraph-2.image-0.src", "formvalue": "src 6"},
{"formname": "paragraph-2.image-1.src", "formvalue": "src 7"},
]
我想把它转换成这个格式:
{'paragraph':
[
{
'image': [{'src': 'src 1'}, {'src': 'src 2'}],
'body': 'body 2',
'title': 'titel 2'
},
{
'image': [{'src': 'src 3'}, {'src': 'src 4'}, {'src': 'src 5'}],
'body': 'body 2',
'title': 'titel 2'
},
{
'image': [{'src': 'src 6'}, {'src': 'src 7'},
'body': 'body 3',
'title': 'titel 3'
},
],
}
如你所见,我把字典和列表混合在一起,这让事情变得有点复杂。在我最后一次尝试中,我已经弄明白了在哪里添加列表,在哪里添加字典。这导致了这样的结果:
{'paragraph': [{'image': []}, {'image': []}, {'image': []}]}
但是当我添加数据时,结果并不是我预期的那样。
{
"paragraph": [{
"body": "bla bla body 1",
"image": {
"src": "src 7"
},
"title": "test titel 1"
}, {
"body": "bla bla body 2",
"image": {
"src": "src 5"
},
"title": "test titel 2"
}, {
"body": "bla bla body 3",
"image": {
"src": "src 3"
},
"title": "test titel 3"
}, {
"image": {
"src": "src 6"
}
}],
"name": "Roel Kramer",
"email": "contact@roelkramer.nl"
}
完整的脚本可以在github gist上查看。我知道它可以更简洁,但等它能正常工作后我会再重构一下。
我到底哪里做错了?我是不是完全忽略了什么?非常感谢!
1 个回答
1
好吧,如果你知道格式会一直保持一致,那么像这样的代码就可以用了:
def add_data(node, name, value):
if '-' not in name:
node[name] = value
else:
key = name[:name.index('-')]
node_index = int(name[len(key) + 1:name.index('.')])
node.setdefault(key, [])
if node_index >= len(node[key]):
node[key].append({})
add_data(node[key][node_index],
name[name.index('.') + 1:],
value)
然后使用的时候,只需要这样做:
root_node = {}
for data in formdata:
add_data(root_node, data['formname'], data['formvalue'])
这个函数有以下几个假设:
- “-”这个符号用来指定某种类型节点的具体节点,后面跟着一个数字。
- “.”这个符号用来分隔树中的节点,并且总是跟在索引数字后面。
- 表单数据总是按顺序排列的。(比如:paragraph-0, paragraph-1, paragraph-2),而不是(paragraph-1, paragraph-0, paragraph-3)。
所以,这里是带有注释的代码,解释得更清楚:
def add_data(node, name, value):
# We're at a parent node (ex: paragraph-0), so we need to drill down until
# we find a leaf node
if '-' in name:
key = name[:name.index('-')]
node_index = int(name[len(key) + 1:name.index('.')])
# Initialize the parent node if needed by giving it a dict to store it's
# information nodes
node.setdefault(key, [])
if node_index >= len(node[key]):
node[key].append({})
# Drill down the tree by calling this function again, making this
# parent node the root
add_data(node[key][node_index],
name[name.index('.') + 1:],
value)
# We're at a leaf node, so just add it to the parent node's information
# ex: The first formdata item would make the root_node dict look like
# { 'name': 'Roel Kramer' }
else:
node[name] = value
这是一个可以运行的例子: http://pastebin.com/wpMPXs1r