在Python中将JSON转换为SQLite - 如何正确地将json密钥映射到数据库列?

时间:2012-01-10 22:59:48

标签: python json sqlite database-design

我想将我创建的JSON文件转换为SQLite数据库。

我的目的是稍后决定哪个数据容器和入口点最好,json(通过文本编辑器输入数据)或SQLite(通过像SQLiteStudio这样的类似电子表格的GUI输入数据)。

我的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)之类的实际数据插入行时,我意识到,因为从JSON文件加载的dict没有特殊顺序,所以它没有正确映射到数据库的列顺序。

所以,我问:“我应该使用哪种策略/方法以编程方式从JSON文件中的每个”块“读取密钥(在本例中,”本地“,”coord“,”sentido“,”veiculos“ ,“modalidade”,“regime”,“pistas”e“medicoes”),使用相同顺序的列创建数据库,然后插入具有适当值的行“?

我对Python有一个很好的经验,但我刚刚开始使用SQL,所以我想就良好实践提供一些建议,而不一定是现成的配方。

1 个答案:

答案 0 :(得分:42)

你有这个python代码:

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

我认为应该是

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

因为% operator要求左边的字符串包含格式代码。

现在你需要做的就是让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 (?,?,?,?,?,?,?)