web-dev-qa-db-fra.com

Comment exporter une base de données MySQL au format JSON?

Je suis intéressé par l’exportation d’un sous-ensemble de valeurs d’une base de données MySQL vers un fichier au format JSON sur disque.

J'ai trouvé un lien qui parle d'un moyen possible de faire cela: http://www.thomasfrank.se/mysql_to_json.html

... mais lorsque j'utilise la méthode de cette page, cela semble fonctionner, mais avec deux problèmes:

1) Il ne renvoie que 15 résultats environ, le dernier étant brusquement coupé (incomplet). Ma requête standard pour cela renvoie environ 4000 résultats lorsque je l'exécute simplement en tant que SELECT name, email FROM students WHERE enrolled IS NULL Mais lorsque je l'exécute en tant que:

SELECT 
     CONCAT("[",
          GROUP_CONCAT(
               CONCAT("{name:'",name,"'"),
               CONCAT(",email:'",email,"'}")
          )
     ,"]") 
AS json FROM students WHERE enrolled IS NULL;

... comme décrit dans le lien, il ne retourne que (comme je l'ai mentionné) 15 résultats. (fwiw, j’ai vérifié ces résultats par rapport aux 4000 que je suis censé obtenir, et ces 15 sont identiques aux 15 premiers des 4000)

2) Il semble y avoir des caractères "d'échappement" dans le fichier lorsque j'ajoute INTO OUTFILE '/path/to/jsonoutput.txt' FIELDS TERMINATED BY ',' à la fin de cette requête. Ainsi, les virgules finissent par ressembler à "\", alors que, évidemment, je voudrais juste avoir les virgules sans le \.

Des idées sur la façon d’obtenir une sortie JSON correcte de MySQL? (Soit en utilisant cette méthode, ou une autre méthode)?

Merci!

45
mindthief

C'est peut-être trop demander à MySQL de s'attendre à ce qu'il produise un json bien formé directement à partir d'une requête. Pensez plutôt à produire quelque chose de plus pratique, tel que CSV (en utilisant l'extrait INTO OUTFILE '/path/to/output.csv' FIELDS TERMINATED BY ',' que vous connaissez déjà), puis à transformer les résultats en json dans un langage prenant en charge cette fonction, comme python ou php.

Edit exemple python, en utilisant le fin SQLAlchemy: 

class Student(object):
    '''The model, a plain, ol python class'''
    def __init__(self, name, email, enrolled):
        self.name = name
        self.email = email
        self.enrolled = enrolled

    def __repr__(self):
        return "<Student(%r, %r)>" % (self.name, self.email)

    def make_dict(self):
        return {'name': self.name, 'email': self.email}



import sqlalchemy
metadata = sqlalchemy.MetaData()
students_table = sqlalchemy.Table('students', metadata,
        sqlalchemy.Column('id', sqlalchemy.Integer, primary_key=True),
        sqlalchemy.Column('name', sqlalchemy.String(100)),
        sqlalchemy.Column('email', sqlalchemy.String(100)),
        sqlalchemy.Column('enrolled', sqlalchemy.Date)
    )

# connect the database.  substitute the needed values.
engine = sqlalchemy.create_engine('mysql://user:pass@Host/database')

# if needed, create the table:
metadata.create_all(engine)

# map the model to the table
import sqlalchemy.orm
sqlalchemy.orm.mapper(Student, students_table)

# now you can issue queries against the database using the mapping:
non_students = engine.query(Student).filter_by(enrolled=None)

# and lets make some json out of it:
import json
non_students_dicts = ( student.make_dict() for student in non_students)
students_json = json.dumps(non_students_dicts)
18

Si vous avez Ruby, vous pouvez installer le répertoire mysql2xxxx gem (pas le mysql2json, qui est un bijou différent):

$ gem install mysql2xxxx

puis lancez la commande

$ mysql2json --user=root --password=password --database=database_name --execute "select * from mytable" >mytable.json

La gem fournit également mysql2csv et mysql2xml. Ce n'est pas aussi rapide que mysqldump, mais il ne souffre pas non plus de certaines bizarreries de mysqldump (par exemple, être capable de vider CSV à partir du même ordinateur que le serveur MySQL lui-même)

34
Seamus Abshere

C’est quelque chose qui devrait être fait dans la couche application.

Par exemple, en php, c’est simple comme bonjour.

__extrait de code

$sql = "select ...";
$db = new PDO ( "mysql:$dbname", $user, $password) ;
$stmt = $db->prepare($sql);
$stmt->execute();
$result = $stmt->fetchAll();

file_put_contents("output.txt", json_encode($result));
10
Byron Whitlock

Une autre possibilité consiste à utiliser MySQL Workbench.

Il existe une option d'exportation JSON dans le menu contextuel du navigateur d'objets et dans le menu de la grille de résultats.

Plus d'informations sur Documentation MySQL: Exportation et importation de données .

9
Wtower

HeidiSQL vous permet de le faire aussi.

Mettez en surbrillance toutes les données dans l'onglet DONNEES ou dans le jeu de résultats de la requête ... puis faites un clic droit et sélectionnez l'option Exporter les lignes de la grille. Cette option vous permet ensuite d'exporter toutes vos données au format JSON, directement dans le presse-papiers ou directement dans un fichier:

 enter image description here

8
jjj

Une autre solution, si vous utilisez Ruby, consiste à écrire un script de connexion à la base de données avec ActiveRecord. Vous devrez d'abord l'installer

bijou installer activerecord

# Ruby ./export-mysql.rb
require 'rubygems'
require 'active_record'

ActiveRecord::Base.establish_connection(
  :adapter => "mysql",
  :database => "database_name",
  :username => "root",
  :password => "",
  :Host => "localhost"
)

class Event < ActiveRecord::Base; end
class Person < ActiveRecord::Base; end

File.open("events.json", "w") { |f| f.write Event.all.to_json }
File.open("people.json", "w") { |f| f.write Person.all.to_json }

Vous pouvez également ajouter des méthodes aux classes ActiveRecord si vous souhaitez manipuler d’abord des données ou inclure ou exclure certaines colonnes.

Person.all.to_json(:only => [ :id, :name ])

Avec ActiveRecord, vous n'êtes pas limité à JSON. Vous pouvez tout aussi facilement exporter que XML ou YAML

Person.all.to_xml
Person.all.to_yaml

Vous n'êtes pas limité à MySQL. Toute base de données supportée par ActiveRecord (Postgres, SQLite3, Oracle ... etc). 

Et il vaut la peine de mentionner que vous pouvez ouvrir un autre handle vers une base

require 'active_record'

ActiveRecord::Base.configurations["mysql"] = {
  :adapter  => 'mysql',
  :database => 'database_name',
  :username => 'root',
  :password => '',
  :Host     => 'localhost'
}


ActiveRecord::Base.configurations["sqlite3"] = {
  :adapter  => 'sqlite3',
  :database => 'db/development.sqlite3'
}

class PersonMySQL < ActiveRecord::Base
  establish_connection "mysql"
end

class PersonSQLite < ActiveRecord::Base
  establish_connection "sqlite3"
end


PersonMySQL.all.each do |person|
    PersonSQLite.create(person.attributes.except("id"))
end

Voici un petit article rapide à ce sujet http://www.seanbehan.com/how-to-export-a-mysql-database-to-json-csv-and-xml-with-Ruby-and-the -activerecord-gem

6
seanbehan

Je sais que c'est vieux, mais pour quelqu'un qui cherche une réponse ... 

Il existe une bibliothèque JSON pour MYSQL que vous pouvez trouver ici Vous devez avoir un accès root sur votre serveur et pouvoir installer des plugins (c'est simple).

1) téléchargez le fichier lib_mysqludf_json.so dans le répertoire plugins de votre installation mysql

2) exécutez le fichier lib_mysqludf_json.sql (il fait pratiquement tout le travail à votre place. Si vous rencontrez des problèmes, supprimez tout ce qui commence par 'DROP FUNCTION ...')

3) encodez votre requête en quelque chose comme ceci:

SELECT json_array(
         group_concat(json_object( name, email))
FROM ....
WHERE ...

et il retournera quelque chose comme

[ 
   { 
     "name": "something",
     "email": "[email protected]"
    }, 
   { 
     "name": "someone",
     "email": "[email protected]"
    }

]
5
Patrick Pease

comme décrit dans le lien, il ne retourne que (comme je l'ai mentionné) 15 résultats. (fwiw, j’ai vérifié ces résultats par rapport aux 4000 que je suis censé obtenir et ces 15 sont les mêmes que les 15 premiers des 4000)

En effet, mysql limite la longueur des données renvoyées par le concat de groupe à la valeur définie dans @@ group_concat_max_len dès qu’elle atteint le montant qu’elle tronque et renvoie le résultat obtenu jusqu’à présent.

Vous pouvez définir @@ group_concat_max_len de différentes manières. référence La documentation mysql ...

2
robot_man

Vous pouvez exporter toute requête SQL en JSON directement à partir de PHPMyAdmin.

2
user2014202

De même, si vous exportez dans la couche d'application, n'oubliez pas de limiter les résultats ..__ Par exemple, si vous avez 10 millions de lignes, vous devriez obtenir les résultats pièce par partie.

1
Hasan Tayyar BESIK

Cela pourrait être une réponse plus spécifique, mais si vous utilisez Windows et MYSQL Workbench, vous pouvez simplement sélectionner la table souhaitée et cliquer sur Exporter/Importer dans la grille des résultats. Cela vous donnera plusieurs options de format, y compris .json

0
Jason

Pour tous ceux qui veulent utiliser Python pour cela, et pouvoir exporter toutes les tables sans prédéfinir les noms de champs, etc., j’ai écrit un court script pour cela l’autre jour, en espérant 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))
0
hwjp

Utilisez le code Ruby suivant

require 'mysql2'

client = Mysql2::Client.new(
  :Host => 'your_Host', `enter code here`
  :database => 'your_database',
  :username => 'your_username', 
  :password => 'your_password')
table_sql = "show tables"
tables = client.query(table_sql, :as => :array)

open('_output.json', 'a') { |f|       
    tables.each do |table|
        sql = "select * from `#{table.first}`"
        res = client.query(sql, :as => :json)
        f.puts res.to_a.join(",") + "\n"
    end
}
0
Rahul Malhotra