Je joue avec une petite application Web dans web.py et je configure une URL pour renvoyer un objet JSON. Quelle est la meilleure façon de convertir une table SQL en JSON en utilisant python?
Personnellement, je préfère SQLObject pour ce genre de chose. J'ai adapté un code de test rapide et sale, je devais obtenir ceci:
import simplejson
from sqlobject import *
# Replace this with the URI for your actual database
connection = connectionForURI('sqlite:/:memory:')
sqlhub.processConnection = connection
# This defines the columns for your database table. See SQLObject docs for how it
# does its conversions for class attributes <-> database columns (underscores to camel
# case, generally)
class Song(SQLObject):
name = StringCol()
artist = StringCol()
album = StringCol()
# Create fake data for demo - this is not needed for the real thing
def MakeFakeDB():
Song.createTable()
s1 = Song(name="B Song",
artist="Artist1",
album="Album1")
s2 = Song(name="A Song",
artist="Artist2",
album="Album2")
def Main():
# This is an iterable, not a list
all_songs = Song.select().orderBy(Song.q.name)
songs_as_dict = []
for song in all_songs:
song_as_dict = {
'name' : song.name,
'artist' : song.artist,
'album' : song.album}
songs_as_dict.append(song_as_dict)
print simplejson.dumps(songs_as_dict)
if __== "__main__":
MakeFakeDB()
Main()
Voici un très bel exemple de ne façon Pythonique de le faire :
import json
import psycopg2
def db(database_name='pepe'):
return psycopg2.connect(database=database_name)
def query_db(query, args=(), one=False):
cur = db().cursor()
cur.execute(query, args)
r = [dict((cur.description[i][0], value) \
for i, value in enumerate(row)) for row in cur.fetchall()]
cur.connection.close()
return (r[0] if r else None) if one else r
my_query = query_db("select * from majorroadstiger limit %s", (3,))
json_output = json.dumps(my_query)
Vous obtenez un tableau d'objets JSON:
>>> json_output
'[{"divroad": "N", "featcat": null, "countyfp": "001",...
Ou avec les éléments suivants:
>>> j2 = query_db("select * from majorroadstiger where fullname= %s limit %s",\
("Mission Blvd", 1), one=True)
vous obtenez un seul objet JSON:
>>> j2 = json.dumps(j2)
>>> j2
'{"divroad": "N", "featcat": null, "countyfp": "001",...
import sqlite3
import json
DB = "./the_database.db"
def get_all_users( json_str = False ):
conn = sqlite3.connect( DB )
conn.row_factory = sqlite3.Row # This enables column access by name: row['column_name']
db = conn.cursor()
rows = db.execute('''
SELECT * from Users
''').fetchall()
conn.commit()
conn.close()
if json_str:
return json.dumps( [dict(ix) for ix in rows] ) #CREATE JSON
return rows
Appelez la méthode no json ...
print get_all_users()
impressions:
[(1, u'orvar', u'password123'), (2, u'kalle', u'password123')]
Appelez la méthode avec json ...
print get_all_users( json_str = True )
impressions:
[{"password": "password123", "id": 1, "name": "orvar"}, {"password": "password123", "id": 2, "name": "kalle"}]
Plus d'informations sur la façon dont vous allez travailler avec vos données avant de les transférer aideraient beaucoup. Le module json fournit des méthodes de vidage (s) et de chargement (s) qui vous aideront si vous utilisez 2.6 ou plus récent: http://docs.python.org/library/json.html .
- MODIFIÉ -
Sans savoir quelles bibliothèques vous utilisez, je ne peux pas vous dire avec certitude si vous trouverez une telle méthode. Normalement, je traiterai des résultats de requête comme celui-ci (exemples avec kinterbasdb parce que c'est ce avec quoi nous travaillons actuellement):
qry = "Select Id, Name, Artist, Album From MP3s Order By Name, Artist"
# Assumes conn is a database connection.
cursor = conn.cursor()
cursor.execute(qry)
rows = [x for x in cursor]
cols = [x[0] for x in cursor.description]
songs = []
for row in rows:
song = {}
for prop, val in Zip(cols, row):
song[prop] = val
songs.append(song)
# Create a string representation of your array of songs.
songsJSON = json.dumps(songs)
Il y a sans aucun doute de meilleurs experts qui auront des listes de compréhension pour éliminer le besoin de boucles écrites, mais cela fonctionne et devrait être quelque chose que vous pourriez adapter à la bibliothèque avec laquelle vous récupérez les enregistrements.
J'ai assemblé un court script qui vide toutes les données de toutes les tables, sous forme de dict du nom de colonne: valeur. Contrairement à d'autres solutions, il ne nécessite aucune information sur ce que sont les tables ou les colonnes, il trouve juste tout et les vide. J'espère que quelqu'un le trouvera utile!
from contextlib import closing
from datetime import datetime
import json
import MySQLdb
DB_NAME = 'x'
DB_USER = 'y'
DB_PASS = 'z'
def get_tables(cursor):
cursor.execute('SHOW tables')
return [r[0] for r in cursor.fetchall()]
def get_rows_as_dicts(cursor, table):
cursor.execute('select * from {}'.format(table))
columns = [d[0] for d in cursor.description]
return [dict(Zip(columns, row)) for row in cursor.fetchall()]
def dump_date(thing):
if isinstance(thing, datetime):
return thing.isoformat()
return str(thing)
with closing(MySQLdb.connect(user=DB_USER, passwd=DB_PASS, db=DB_NAME)) as conn, closing(conn.cursor()) as cursor:
dump = {}
for table in get_tables(cursor):
dump[table] = get_rows_as_dicts(cursor, table)
print(json.dumps(dump, default=dump_date, indent=2))
personne ne semble avoir offert la possibilité d'obtenir le JSON directement à partir du serveur Postgresql, en utilisant la capacité JSON postgres https://www.postgresql.org/docs/9.4/static/functions-json.html
Pas d'analyse, de boucle ou de consommation de mémoire du côté python, que vous voudrez peut-être vraiment considérer si vous avez affaire à 100 000 ou des millions de lignes.
from Django.db import connection
sql = 'SELECT to_json(result) FROM (SELECT * FROM TABLE table) result)'
with connection.cursor() as cursor:
cursor.execute(sql)
output = cursor.fetchall()
une table comme:
id, value
----------
1 3
2 7
renverra un Python objet JSON
[{"id": 1, "value": 3},{"id":2, "value": 7}]
Utilisez ensuite json.dumps
à vider en tant que chaîne JSON
Je compléterais The Demz réponse avec la version psycopg2:
import psycopg2
import psycopg2.extras
import json
connection = psycopg2.connect(dbname=_cdatabase, Host=_chost, port=_cport , user=_cuser, password=_cpassword)
cursor = connection.cursor(cursor_factory=psycopg2.extras.DictCursor) # This line allows dictionary access.
#select some records into "rows"
jsonout= json.dumps([dict(ix) for ix in rows])
Le moyen le plus simple,
utilisation json.dumps
mais si son datetime nécessitera d'analyser datetime dans json sérialiseur.
voici le mien,
import MySQLdb, re, json
from datetime import date, datetime
def json_serial(obj):
"""JSON serializer for objects not serializable by default json code"""
if isinstance(obj, (datetime, date)):
return obj.isoformat()
raise TypeError ("Type %s not serializable" % type(obj))
conn = MySQLdb.connect(instance)
curr = conn.cursor()
curr.execute("SELECT * FROM `assets`")
data = curr.fetchall()
print json.dumps(data, default=json_serial)
il renverra json dump
ne autre méthode simple sans vidages json, ici, obtenez l'en-tête et utilisez Zip pour mapper avec chacun finalement fait en json mais ce n'est pas changer datetime en sérialiseur json ...
data_json = []
header = [i[0] for i in curr.description]
data = curr.fetchall()
for i in data:
data_json.append(dict(Zip(header, i)))
print data_json
Si vous utilisez un serveur MSSQL 2008 et supérieur, vous pouvez effectuer votre requête SELECT
pour renvoyer json en utilisant le FOR JSON AUTO
clause E.G
SELECT name, surname FROM users FOR JSON AUTO
Rendra Json comme
[{"name": "Jane","surname": "Doe" }, {"name": "Foo","surname": "Samantha" }, ..., {"name": "John", "surname": "boo" }]
depuis sqlalchemy import Colonne depuis sqlalchemy import Entier depuis sqlalchemy import Chaîne
Base = déclarative_base () métadonnées = Base.metadata
classe UserTable (Base): nom_table = 'UserTable'
Id = Column("ID", Integer, primary_key=True)
Name = Column("Name", String(100))
classe UserTableDTO: def init (self, ob): self.Id = ob.Id self.Name = ob.Name
lignes = dbsession.query (Table) .all ()
json_string = [json.loads (json.dumps (UserTableDTO (ob). dict , default = lambda x: str (x))) pour ob in lignes] print (json_string)