web-dev-qa-db-fra.com

Convertir JSON en SQLite en Python - Comment mapper correctement les clés json aux colonnes de la base de données?

Je souhaite convertir un fichier JSON que j'ai créé en une base de données SQLite.

Mon intention est de décider plus tard quel conteneur de données et point d'entrée est le meilleur, json (saisie de données via l'éditeur de texte) ou SQLite (saisie de données via des GUI de type tableur comme SQLiteStudio).

Mon fichier json est comme ceci (contenant les données de trafic de certains carrefours dans ma ville):

...
"2011-12-17 16:00": {
    "local": "Av. Protásio Alves; esquina Ramiro Barcelos",
    "coord": "-30.036916,-51.208093",
    "sentido": "bairro-centro",
    "veiculos": "automotores",
    "modalidade": "semaforo 50-15",
    "regime": "típico",
    "pistas": "2+c",
    "medicoes": [
        [32, 50],
        [40, 50],
        [29, 50],
        [32, 50],
        [35, 50]
        ]
    },
"2011-12-19 08:38": {
    "local": "R. Fernandes Vieira; esquina Protásio Alves",
    "coord": "-30.035535,-51.211079",
    "sentido": "único",
    "veiculos": "automotores",
    "modalidade": "semáforo 30-70",
    "regime": "típico",
    "pistas": "3",
    "medicoes": [
        [23, 30],
        [32, 30],
        [33, 30],
        [32, 30]
        ]
    }
...

Et j'ai créé une base de données Nice avec une relation un-à-plusieurs avec ces lignes de Python:

import sqlite3

db = sqlite3.connect("fluxos.sqlite")
c = db.cursor()

c.execute('''create table medicoes
         (timestamp text primary key,
          local text,
          coord text,
          sentido text,
          veiculos text,
          modalidade text,
          pistas text)''')

c.execute('''create table valores
         (id integer primary key,
          quantidade integer,
          tempo integer,
          foreign key (id) references medicoes(timestamp))''')

MAIS le problème est que, lorsque je me préparais à insérer les lignes avec des données réelles avec quelque chose comme c.execute("insert into medicoes values(?,?,?,?,?,?,?)" % keys), je me suis rendu compte que, puisque le dict chargé à partir du fichier JSON n'a pas d'ordre spécial, il ne correspond pas correctement à l'ordre des colonnes de la base de données.

Je demande donc: "quelle stratégie/méthode dois-je utiliser pour lire par programme les clés de chaque" bloc "du fichier JSON (dans ce cas," local "," coord "," sentido "," veiculos "," modalidade "," régime "," pistas "et" médecins "), créez la base de données avec les colonnes dans le même ordre, puis insérez les lignes avec les valeurs appropriées"?

J'ai une bonne expérience avec Python, mais je ne fais que commencer avec SQL, donc j'aimerais avoir des conseils sur les bonnes pratiques, et pas nécessairement une recette prête.

44
heltonbiker

Vous avez ce code python:

c.execute("insert into medicoes values(?,?,?,?,?,?,?)" % keys)

qui je pense devrait être

c.execute("insert into medicoes values (?,?,?,?,?,?,?)", keys)

puisque le % operator s'attend à ce que la chaîne à gauche contienne des codes de formatage.

Maintenant, tout ce dont vous avez besoin pour que cela fonctionne est que keys soit un Tuple (ou une liste) contenant les valeurs de la nouvelle ligne de la table medicoes dans le bon ordre. Considérez le code python suivant:

import json

traffic = json.load(open('xxx.json'))

columns = ['local', 'coord', 'sentido', 'veiculos', 'modalidade', 'pistas']
for timestamp, data in traffic.iteritems():
    keys = (timestamp,) + Tuple(data[c] for c in columns)
    print str(keys)

Lorsque je lance cela avec vos exemples de données, j'obtiens:

(u'2011-12-19 08:38', u'R. Fernandes Vieira; esquina Prot\xe1sio Alves', u'-30.035535,-51.211079', u'\xfanico', u'automotores', u'sem\xe1foro 30-70', u'3')
(u'2011-12-17 16:00', u'Av. Prot\xe1sio Alves; esquina Ramiro Barcelos', u'-30.036916,-51.208093', u'bairro-centro', u'automotores', u'semaforo 50-15', u'2+c')

qui semblent être les tuples dont vous avez besoin.

Vous pouvez ajouter le code sqlite nécessaire avec quelque chose comme ceci:

import json
import sqlite3

traffic = json.load(open('xxx.json'))
db = sqlite3.connect("fluxos.sqlite")

query = "insert into medicoes values (?,?,?,?,?,?,?)"
columns = ['local', 'coord', 'sentido', 'veiculos', 'modalidade', 'pistas']
for timestamp, data in traffic.iteritems():
    keys = (timestamp,) + Tuple(data[c] for c in columns)
    c = db.cursor()
    c.execute(query, keys)
    c.close()

Modifier: si vous ne voulez pas coder en dur la liste des colonnes, vous pouvez faire quelque chose comme ceci:

import json

traffic = json.load(open('xxx.json'))

someitem = traffic.itervalues().next()
columns = list(someitem.keys())
print columns

Lorsque je lance cela, il affiche:

[u'medicoes', u'veiculos', u'coord', u'modalidade', u'sentido', u'local', u'pistas', u'regime']

Vous pouvez l'utiliser avec quelque chose comme ceci:

import json
import sqlite3

db = sqlite3.connect('fluxos.sqlite')
traffic = json.load(open('xxx.json'))

someitem = traffic.itervalues().next()
columns = list(someitem.keys())
columns.remove('medicoes')
columns.remove('regime')

query = "insert into medicoes (timestamp,{0}) values (?{1})"
query = query.format(",".join(columns), ",?" * len(columns))
print query

for timestamp, data in traffic.iteritems():
    keys = (timestamp,) + Tuple(data[c] for c in columns)
    c = db.cursor()
    c.execute(query)
    c.close()

La requête que ce code imprime lorsque je l'essaye avec vos exemples de données est quelque chose comme ceci:

insert into medicoes (timestamp,veiculos,coord,modalidade,sentido,local,pistas) values (?,?,?,?,?,?,?)
44
srgerg