2010-07-20 72 views

Respuesta

14

Personalmente prefiero SQLObject para este tipo de cosas. He adaptado un código de prueba rápida y sucia, que tenía que conseguir esto:

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 __name__ == "__main__": 
    MakeFakeDB() 
    Main() 
+0

gracias detly. esto funciona bien, aunque llegué a un error al tener la lista y el dict nombrados de la misma manera. acaba de renombrar el dict a 'songs' y todo funciona bien. –

+0

Me alegro de poder ayudar. Es extraño que haya un error, como veo, tienen nombres (ligeramente) diferentes, ¿podrías haber cometido un error tipográfico? – detly

+0

ah, ya veo. Probablemente lo hice –

13

Más información acerca de cómo va a trabajar con sus datos antes de transferirlo ayudaría mucho. El módulo json proporciona volcado (s) y carga (s) métodos que te ayudarán si estás usando 2.6 o más reciente: http://docs.python.org/library/json.html.

- EDITADO -

Sin saber qué bibliotecas que está utilizando no puedo decir con seguridad si usted encontrará un método así. Normalmente, voy a procesar los resultados de consulta como la siguiente (ejemplos con KInterbasDB porque es lo que estamos trabajando actualmente con):

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) 

Sin duda hay mejores expertos por ahí que va a tener listas por comprensión para eliminar la necesidad de Bucles escritos, pero esto funciona y debería ser algo que puedas adaptar a cualquier biblioteca con la que estés recuperando registros.

+0

la tabla es una lista de archivos mp3, incluido el nombre de la pista, el artista y la url, que luego se utiliza para completar un reproductor de audio HTML5. El jugador crea una lista de reproducción a través de un objeto JSON, así que solo estoy buscando pasar la tabla a JSON. Miré los documentos, pero me preguntaba si había algo parecido al método 'to_json' de ruby ​​en Python. –

+0

@ aaron-moodie - He actualizado mi respuesta con más código de ejemplo. Espero que ayude. –

+0

Buen enfoque, pero tuve que hacer dos cambios para que funcione para mí. las canciones deben ser un diccionario: "songs = {}" y en lugar de songs.append (song) utilicé canciones [song ['Id']] = song. De lo contrario, json.dumps (canciones) se detendrá con el error de que las canciones no se pueden serializar. –

54

Aquí es un muy buen ejemplo de a pythonic way to do that:

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) 

Se obtiene una matriz de objetos JSON:

>>> json_output 
'[{"divroad": "N", "featcat": null, "countyfp": "001",... 

con lo siguiente:

>>> j2 = query_db("select * from majorroadstiger where fullname= %s limit %s",\ 
("Mission Blvd", 1), one=True) 

se obtiene un único objeto JSON:

>>> j2 = json.dumps(j2) 
>>> j2 
'{"divroad": "N", "featcat": null, "countyfp": "001",... 
+1

¡Excelente respuesta! Lee tantas respuestas complicadas tipo "convertir a objeto" que esto es simplemente sorprendente. ¡GRACIAS! – andig

+0

estoy completamente de acuerdo con el comentario anterior. esta es una hermosa solución. –

+0

Esto no admite MUESTRAS en tablas con una relación de uno a muchos muy bien. Obtendrá filas con datos repetidos. Necesita un ORM como la respuesta aceptada para obtener algo que solucione este problema. Para SQL simple a JSON esto funcionará bien sin embargo. – Banjocat

17
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 

Callin el método sin JSON ...

print get_all_users() 

impresiones:

[(1, u'orvar', u'password123'), (2, u'kalle', u'password123')] 

Callin con el método json ...

print get_all_users(json_str = True) 

impresiones:

[{"password": "password123", "id": 1, "name": "orvar"}, {"password": "password123", "id": 2, "name": "kalle"}] 
4

me llamaron juntos un pequeño script que vuelca todos los datos de todas las tablas, como se predice de nombre de la columna: valor. A diferencia de otras soluciones, no requiere información sobre las tablas o columnas, solo encuentra todo y lo descarga. ¡Espero que alguien lo encuentre útil!

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

Me complementar The Demz respuesta con la versión 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]) 
1

nadie parece haber ofrecido la opción de obtener el JSON directamente desde el servidor PostgreSQL, utilizando la capacidad de postgres JSON https://www.postgresql.org/docs/9.4/static/functions-json.html

Sin análisis, bucles o consumo de memoria en el lado de Python, que realmente puede considerar si se trata de 100.000 o millones de filas.

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

una tabla como:

id, value 
---------- 
1  3 
2  7 

devolverá un objeto Python JSON

[{"id": 1, "value": 3},{"id":2, "value": 7}] 

A continuación, utilice json.dumps para volcar como una cadena JSON manera

+0

¿podría hacerse esto usando solo las funciones' psycopg2' y PostgreSQL 'JSON'? – sc28

+0

conexión y cursor psycopg2 harían lo mismo – MrE

+0

¡Gracias por aclarar! Confirmé que de hecho funciona con psycopg2. Como ejemplo, utilicé la función 'json_agg()' como se describe [aquí] (http://johnatten.com/2015/04/22/use-postgres-json-type-and-aggregate-functions-to-map -relational-data-to-json /) – sc28

0

más sencilla,

use json.dumps pero si su fecha y hora requerirá analizar el datetime en json serializer.

aquí es mío,

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) 

volverá JSON vertedero método

una más sencilla y sin JSON vertederos, aquí Largo cabecera y usar zip para asignar a cada finalmente lo hizo como JSON, pero este no es el cambio de fecha y hora en serializador 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 
Cuestiones relacionadas