web-dev-qa-db-fra.com

Génération d'un objet et d'un tableau JSON imbriqués dynamiques - python

Comme la question explique le problème, j'ai essayé de générer un objet JSON imbriqué. Dans ce cas, j'ai for boucles pour extraire les données du dictionnaire dic. Voici le code:

f = open("test_json.txt", 'w')
flag = False
temp = ""
start = "{\n\t\"filename\"" + " : \"" +initial_filename+"\",\n\t\"data\"" +" : " +" [\n"
end = "\n\t]" +"\n}"
f.write(start)
for i, (key,value) in enumerate(dic.iteritems()):
    f.write("{\n\t\"keyword\":"+"\""+str(key)+"\""+",\n")
    f.write("\"term_freq\":"+str(len(value))+",\n")
    f.write("\"lists\":[\n\t")
    for item in value:
        f.write("{\n")
        f.write("\t\t\"occurance\" :"+str(item)+"\n")
        #Check last object
        if value.index(item)+1 == len(value):
            f.write("}\n" 
            f.write("]\n")
        else:
            f.write("},") # close occurrence object
    # Check last item in dic
    if i == len(dic)-1:
        flag = True
    if(flag):
        f.write("}")
    else:
        f.write("},") #close lists object
        flag = False 

#check for flag
f.write("]") #close lists array 
f.write("}")

La sortie attendue est:

{
"filename": "abc.pdf",
"data": [{
    "keyword": "irritation",
    "term_freq": 5,
    "lists": [{
        "occurance": 1
    }, {
        "occurance": 1
    }, {
        "occurance": 1
    }, {
        "occurance": 1
    }, {
        "occurance": 2
    }]
}, {
    "keyword": "bomber",
    "lists": [{
        "occurance": 1
    }, {
        "occurance": 1
    }, {
        "occurance": 1
    }, {
        "occurance": 1
    }, {
        "occurance": 2
    }],
    "term_freq": 5
}]
}

Mais actuellement, j'obtiens une sortie comme ci-dessous:

{
"filename": "abc.pdf",
"data": [{
    "keyword": "irritation",
    "term_freq": 5,
    "lists": [{
        "occurance": 1
    }, {
        "occurance": 1
    }, {
        "occurance": 1
    }, {
        "occurance": 1
    }, {
        "occurance": 2
    },]                // Here lies the problem "," before array(last element)
}, {
    "keyword": "bomber",
    "lists": [{
        "occurance": 1
    }, {
        "occurance": 1
    }, {
        "occurance": 1
    }, {
        "occurance": 1
    }, {
        "occurance": 2
    },],                  // Here lies the problem "," before array(last element)
    "term_freq": 5
}]
}

Aidez-moi, j'ai essayé de le résoudre, mais j'ai échoué. Veuillez ne pas le marquer comme étant en double car j'ai déjà vérifié d'autres réponses et je n'ai pas aidé du tout.

Edit 1: L'entrée provient essentiellement d'un dictionnaire dic dont le type de mappage est <String, List> par exemple: "irritation" => [1,3,5,7,8] où l'irritation est la clé, et mappé sur une liste de numéros de page. Ceci est essentiellement lu dans la boucle for externe où key est le mot-clé et value est une liste de pages d'occurrence de ce mot-clé.

Modifier 2:

dic = collections.defaultdict(list) # declaring the variable dictionary
dic[key].append(value) # inserting the values - useless to tell here
for key in dic:
    # Here dic[x] represents list - each value of x
    print key,":",dic[x],"\n" #prints the data in dictionary
8
Asif Ali

Qu'est-ce que @ andrea-f me semble bien, voici une autre solution:

N'hésitez pas à choisir les deux :)

import json

dic = {
        "bomber": [1, 2, 3, 4, 5],
        "irritation": [1, 3, 5, 7, 8]
      }

filename = "abc.pdf"

json_dict = {}
data = []

for k, v in dic.iteritems():
  tmp_dict = {}
  tmp_dict["keyword"] = k
  tmp_dict["term_freq"] = len(v)
  tmp_dict["lists"] = [{"occurrance": i} for i in v]
  data.append(tmp_dict)

json_dict["filename"] = filename
json_dict["data"] = data

with open("abc.json", "w") as outfile:
    json.dump(json_dict, outfile, indent=4, sort_keys=True)

C'est la même idée, je crée d'abord un grand json_dict À enregistrer directement dans json. J'utilise l'instruction with pour enregistrer le json en évitant la capture de exception

De plus, vous devriez jeter un œil au doc ​​de json.dumps() si vous avez besoin d'une amélioration future de votre sortie json.

[~ # ~] modifier [~ # ~]

Et juste pour le plaisir, si vous n'aimez pas tmp var, vous pouvez faire toutes les données for en boucle dans une ligne :)

json_dict["data"] = [{"keyword": k, "term_freq": len(v), "lists": [{"occurrance": i} for i in v]} for k, v in dic.iteritems()]

Cela pourrait donner à la solution finale quelque chose de pas totalement lisible comme ceci:

import json

json_dict = {
              "filename": "abc.pdf",
              "data": [{
                        "keyword": k,
                        "term_freq": len(v),
                        "lists": [{"occurrance": i} for i in v]
                       } for k, v in dic.iteritems()]
            }

with open("abc.json", "w") as outfile:
    json.dump(json_dict, outfile, indent=4, sort_keys=True)

EDIT 2

Il semble que vous ne souhaitiez pas enregistrer votre json en tant que sortie souhaitée, mais être capable de lire.

En fait, vous pouvez également utiliser json.dumps() pour imprimer votre json.

with open('abc.json', 'r') as handle:
    new_json_dict = json.load(handle)
    print json.dumps(json_dict, indent=4, sort_keys=True)

Il y a cependant un problème ici, "filename": Est imprimé à la fin de la liste car le d de data précède le f.

Pour forcer la commande, vous devrez utiliser un OrderedDict dans la génération du dict. Attention la syntaxe est moche (imo) avec python 2.X

Voici la nouvelle solution complète;)

import json
from collections import OrderedDict

dic = {
        'bomber': [1, 2, 3, 4, 5],
        'irritation': [1, 3, 5, 7, 8]
      }

json_dict = OrderedDict([
              ('filename', 'abc.pdf'),
              ('data', [ OrderedDict([
                                        ('keyword', k),
                                        ('term_freq', len(v)),
                                        ('lists', [{'occurrance': i} for i in v])
                                     ]) for k, v in dic.iteritems()])
            ])

with open('abc.json', 'w') as outfile:
    json.dump(json_dict, outfile)


# Now to read the orderer json file

with open('abc.json', 'r') as handle:
    new_json_dict = json.load(handle, object_pairs_hook=OrderedDict)
    print json.dumps(json_dict, indent=4)

Sortira:

{
    "filename": "abc.pdf", 
    "data": [
        {
            "keyword": "bomber", 
            "term_freq": 5, 
            "lists": [
                {
                    "occurrance": 1
                }, 
                {
                    "occurrance": 2
                }, 
                {
                    "occurrance": 3
                }, 
                {
                    "occurrance": 4
                }, 
                {
                    "occurrance": 5
                }
            ]
        }, 
        {
            "keyword": "irritation", 
            "term_freq": 5, 
            "lists": [
                {
                    "occurrance": 1
                }, 
                {
                    "occurrance": 3
                }, 
                {
                    "occurrance": 5
                }, 
                {
                    "occurrance": 7
                }, 
                {
                    "occurrance": 8
                }
            ]
        }
    ]
}

Mais attention, la plupart du temps, il est préférable de sauvegarder un fichier régulier.json Afin d'être cross-langues.

7
Kruupös

Votre code actuel ne fonctionne pas car la boucle parcourt l'avant-dernier élément en ajoutant le }, puis lorsque la boucle s'exécute à nouveau, elle définit l'indicateur sur false, mais la dernière fois qu'elle a été exécutée, elle a ajouté un , car il pensait qu'il y aurait un autre élément.

Si tel est votre dict: a = {"bomber":[1,2,3,4,5]} alors vous pouvez faire:

import json
file_name = "a_file.json"
file_name_input = "abc.pdf"
new_output = {}
new_output["filename"] = file_name_input

new_data = []
i = 0
for key, val in a.iteritems():
   new_data.append({"keyword":key, "lists":[], "term_freq":len(val)})
   for p in val:
       new_data[i]["lists"].append({"occurrance":p})
   i += 1

new_output['data'] = new_data

Enregistrez ensuite les données en:

f = open(file_name, 'w+')
f.write(json.dumps(new_output, indent=4, sort_keys=True, default=unicode))
f.close()
2
andrea-f