web-dev-qa-db-fra.com

plusieurs objets Json dans un fichier extrait par python

Je suis très nouveau dans les fichiers Json. Si j’ai un fichier json avec plusieurs objets json tels que:

{"ID":"12345","Timestamp":"20140101", "Usefulness":"Yes",
  "Code":[{"event1":"A","result":"1"},…]}
{"ID":"1A35B","Timestamp":"20140102", "Usefulness":"No",
  "Code":[{"event1":"B","result":"1"},…]}
{"ID":"AA356","Timestamp":"20140103", "Usefulness":"No",
  "Code":[{"event1":"B","result":"0"},…]}
…

Je veux extraire tous les "timestamp" et "utilité" dans un cadre de données:

    Timestamp    Usefulness
 0   20140101      Yes
 1   20140102      No
 2   20140103      No
 …

Est-ce que quelqu'un connaît un moyen général de traiter de tels problèmes? Merci!

26
user6396

Utilisez un tableau JSON, au format:

[
{"ID":"12345","Timestamp":"20140101", "Usefulness":"Yes",
  "Code":[{"event1":"A","result":"1"},…]},
{"ID":"1A35B","Timestamp":"20140102", "Usefulness":"No",
  "Code":[{"event1":"B","result":"1"},…]},
{"ID":"AA356","Timestamp":"20140103", "Usefulness":"No",
  "Code":[{"event1":"B","result":"0"},…]},
...
]

Puis importez-le dans votre code python

import json

with open('file.json') as json_file:

    data = json.load(json_file)

Maintenant, le contenu des données est un tableau avec des dictionnaires représentant chacun des éléments.

Vous pouvez y accéder facilement, à savoir:

data[0]["ID"]
21
danielfranca

Vous pouvez utiliser json.JSONDecoder.raw_decode pour décoder des chaînes arbitrairement grandes de JSON "empilés" (tant qu'elles peuvent tenir dans la mémoire). raw_decode s'arrête une fois qu'il a un objet valide et renvoie la dernière position où ne faisait pas partie de l'objet analysé. Ce n'est pas documenté, mais vous pouvez repasser cette position à raw_decode et il recommence à analyser à partir de cette position. Malheureusement, le module Python json n'accepte pas les chaînes dont les espaces sont précédés de préfixes. Nous devons donc effectuer une recherche pour trouver la première partie de votre document ne contenant pas d'espaces.

from json import JSONDecoder, JSONDecodeError
import re

NOT_WHITESPACE = re.compile(r'[^\s]')

def decode_stacked(document, pos=0, decoder=JSONDecoder()):
    while True:
        match = NOT_WHITESPACE.search(document, pos)
        if not match:
            return
        pos = match.start()

        try:
            obj, pos = decoder.raw_decode(document, pos)
        except JSONDecodeError:
            # do something sensible if there's some error
            raise
        yield obj

s = """

{"a": 1}  


   [
1
,   
2
]


"""

for obj in decode_stacked(s):
    print(obj)

impressions:

{'a': 1}
[1, 2]
57
Dunes

Ainsi, comme il a été mentionné dans quelques commentaires contenant les données d’un tableau, c’est plus simple, mais la solution n’évolue pas bien en termes d’efficacité lorsque la taille du jeu de données augmente. Vous ne devriez utiliser un itérateur que lorsque vous souhaitez accéder à un objet aléatoire du tableau, sinon, les générateurs sont la voie à suivre. Ci-dessous, j'ai prototypé une fonction de lecture qui lit chaque objet json individuellement et renvoie un générateur.

L'idée de base est de signaler au lecteur qu'il doit se scinder sur le caractère chariot "\ n" (ou "\ r\n" pour Windows). Python peut le faire avec la fonction file. Readline ().

import json
def json_readr(file):
    for line in open(file, mode="r"):
        yield json.loads(line)

Cependant, cette méthode ne fonctionne vraiment que lorsque le fichier est écrit tel que vous l'avez, chaque objet étant séparé par un nouveau caractère de ligne. Ci-dessous, j'ai écrit un exemple d'écrivain qui sépare un tableau d'objets JSON et les enregistre sur une nouvelle ligne.

def json_writr(file, json_objects):
    f = open(file, mode="w")
    for jsonobj in json_objects:
        jsonstr = json.dumps(jsonobj)
        f.write(jsonstr+"\n")
    f.flush()
    f.close()

Vous pouvez également faire la même opération avec file. Writeelines () et list comprehension

...
    jsobjs = [json.dumps(j)+"\n" for j in json_objects]
    f.writelines(jsobjs)
...

Et si vous vouliez ajouter les données au lieu d'écrire un nouveau fichier, changez simplement 'mode = "w"' en 'mode = "a"'.

En fin de compte, je trouve que cela aide beaucoup non seulement à la lisibilité lorsque j'essaie d'ouvrir des fichiers JSON dans un éditeur de texte, mais également à une utilisation plus efficace de la mémoire.

Sur cette note, si vous changez d’esprit à un moment donné et que vous souhaitez obtenir une liste du lecteur, Python vous permet de placer une fonction de générateur dans une liste et de la remplir automatiquement. Dans mots, il suffit d'écrire

lst = list(json_readr(file))

J'espère que cela t'aides. Désolé si c'était un peu bavard.

7
Dan Temkin