2010-07-16 5 views
0

Je souhaite convertir des données de forme plate en données JSON récursives en python ou javascript. Ces données JSON peuvent ensuite être interprétées par un moteur de template (google for tempest, il a une syntaxe similaire à django). Il existe de nombreux exemples de conversion de données à données récursives, mais le problème est qu'il ne peut s'agir que d'un dict ou d'une liste.Données de formulaire HTML à json dict

J'ai essayé de le faire de plusieurs façons, mais je n'ai pas encore réussi. Alors après m'être gratté la tête pendant au moins deux semaines, j'ai décidé de poser une question ici.

Le formdata est comme celui-ci (les noms clés peuvent être différentes):

formdata = [ 
    {"formname": "name", "formvalue": "Roel Kramer"}, 
    {"formname": "email", "formvalue": "[email protected]"}, 
    {"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"}, 
] 

Je voudrais le convertir en ce format:

{'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' 
     }, 
    ], 
} 

Comme vous pouvez le voir je mélange dicts avec des listes , ce qui le rend un peu plus difficile. Dans ma dernière tentative, je suis arrivé au point où le script détermine où ajouter des listes et où ajouter des dicts. Il en résulte:

{'paragraph': [{'image': []}, {'image': []}, {'image': []}]} 

Mais lorsque j'ajoute des données, le résultat n'est pas ce que j'attendais. Le script total peut être vu à github gist. Je sais que ça peut être beaucoup plus propre, mais je vais le refactoriser quand ça marche.

Qu'est-ce que je fais mal? Est-ce que je manque complètement quelque chose? Merci beaucoup!

Répondre

1

Eh bien, si vous connaissez le format sera compatible alors quelque chose comme ceci fonctionne:

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) 

ensuite l'utiliser, il suffit de faire quelque chose comme ceci:

root_node = {} 
for data in formdata: 
    add_data(root_node, data['formname'], data['formvalue']) 

La fonction rend la hypothèses suivantes:

  1. Le caractère - est utilisé pour spécifier quel noeud d'un type de noeud particulier, et est suivi par un nombre.
  2. Le. caractère sépare les nœuds dans l'arborescence et suit toujours le numéro d'index.
  3. Les données de formulaire iront toujours dans l'ordre. (paragraphe-0, paragraphe-1, paragraphe-2) au lieu de (paragraphe-1, paragraphe-0, paragraphe -3).

Alors, voici le code avec des commentaires expliquant qu'il:

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 

Voici un exemple de travail: http://pastebin.com/wpMPXs1r

+0

Merci beaucoup eric! Cela m'a vraiment aidé. Les commentaires rendent tout clair. Je ne savais pas non plus de {} .setdefault. Je ne peux pas voter pour vous .. devez d'abord établir une réputation. –

+0

Je suis content que je puisse aider! Vous pouvez toujours accepter la réponse. Cliquez simplement sur la coche sous les flèches de vote. –

Questions connexes