Конвертировать JSON в SQLite в Python - Как правильно сопоставить ключи JSON со столбцами базы данных? - PullRequest
43 голосов
/ 11 января 2012

Я хочу преобразовать созданный мной файл JSON в базу данных SQLite.

В дальнейшем я намерен решить, какой контейнер данных и точка входа лучше: json (ввод данных через текстовый редактор) или SQLite (ввод данных через графические интерфейсы, подобные электронным таблицам, например SQLiteStudio).

Мой файл json выглядит следующим образом (содержит данные о трафике с некоторых перекрестков в моем городе):

...
"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]
        ]
    }
...

И я создал хорошую базу данных с отношением один ко многим с помощью следующих строк кода 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))''')

НО проблема в том, что когда я готовился вставить строки с фактическими данными с чем-то вроде c.execute("insert into medicoes values(?,?,?,?,?,?,?)" % keys), я понял, что, поскольку dict, загруженный из файла JSON, не имеет специального порядка, он не отображается должным образом на порядок столбцов базы данных.

Итак, я спрашиваю: «какую стратегию / метод следует использовать для программного считывания ключей из каждого« блока »в файле JSON (в данном случае« local », «ordin», «sentido», «veiculos») , "modalidade", "mode", "pistas" и "medicoes"), создайте базу данных со столбцами в том же порядке, а затем вставьте строки с правильными значениями "?

У меня хороший опыт работы с Python, но я только начинаю с SQL, поэтому я хотел бы получить несколько советов о передовой практике, а не обязательно готовый рецепт.

1 Ответ

44 голосов
/ 11 января 2012

У вас есть этот код Python:

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

которое, я думаю, должно быть

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

, поскольку оператор % ожидает, что строка слева содержит коды форматирования.

Теперь все, что вам нужно для этой работы, - это чтобы keys был кортежем (или списком), содержащим значения для новой строки таблицы Medicoes в правильном порядке. Рассмотрим следующий код Python:

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)

Когда я запускаю это с вашими примерами данных, я получаю:

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

, который может показаться нужным вам кортежем.

Вы можете добавить необходимый sqlite-код примерно так:

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()

Редактировать: Если вы не хотите жестко кодировать список столбцов, вы можете сделать что-то вроде этого:

import json

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

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

Когда я запускаю это, он печатает:

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

Вы можете использовать его с чем-то вроде этого:

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()

Запрос, который печатает этот код, когда я пробую его с вашими примерами данных, выглядит примерно так:

insert into medicoes (timestamp,veiculos,coord,modalidade,sentido,local,pistas) values (?,?,?,?,?,?,?)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...