代码之家  ›  专栏  ›  技术社区  ›  Roel Kramer

将HTML表单数据转换为递归JSON dict

  •  0
  • Roel Kramer  · 技术社区  · 14 年前

    我想用python或javascript将平面表单数据转换为递归JSON数据。这个JSON数据稍后可以由模板引擎解释(Google对于tempest,它有类似于django的语法)。有很多例子可以将平面数据转换为递归数据,但问题是它不能是dict或list。

    我试过很多方法,但还没有成功。所以,在挠头至少两周后,我决定在这里问一个问题。

    FormData如下(键名可能不同):

    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 回复  |  直到 14 年前
        1
  •  1
  •   Eric Palakovich Carr    14 年前

    好吧,如果你知道格式是一致的,那么像这样的东西就可以工作了:

    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'])
    

    该函数进行以下假设:

    1. -字符用于指定特定节点类型的节点,后面跟着 一个数字。
    2. 这个。字符分隔树中的节点,并始终遵循索引号。
    3. 表单数据将始终按顺序排列。(第0段、第1段、第2段)而不是(第1段、第0段、第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