简体   繁体   English

Python将mysql查询结果转换为json

[英]Python converting mysql query result to json

I'm trying to implement REST APIs and part of it is formatting data into json.我正在尝试实现 REST API,其中一部分是将数据格式化为 json。 I am able to retrieve data from a mysql database, however the object i receive is not what I expect.我能够从 mysql 数据库中检索数据,但是我收到的对象不是我所期望的。 here is my code这是我的代码

from flask import Flask
from flask.ext.mysqldb import MySQL

app = Flask(__name__)
app.config['MYSQL_HOST'] = '127.0.0.1'
app.config['MYSQL_USER'] = 'root'
app.config['MYSQL_PASSWORD'] = 'password'
app.config['MYSQL_DB'] = 'hello_db'
mysql = MySQL(app)

@app.route('/hello')
def index():
   cur = mysql.connection.cursor()
   cur.execute('''SELECT * FROM Users WHERE id=1''')
   rv = cur.fetchall()
   return str(rv)

if __name__ == '__main__':
   app.run(debug=True)

Outcome:结果:

((1L, u'my_username', u'my_password'),)

How do I achieve to return a json format like this:我如何实现返回这样的 json 格式:

{
 "id":1, 
 "username":"my_username", 
 "password":"my_password"
}

You can use cursor description to extract row headers: row_headers=[x[0] for x in cursor.description] after the execute statement.您可以在执行语句之后使用游标描述来提取行标题: row_headers=[x[0] for x in cursor.description] Then you can zip it with the result of sql to produce json data.然后就可以用sql的结果压缩生成json数据了。 So your code will be something like:所以你的代码将是这样的:

from flask import Flask
from flask.ext.mysqldb import MySQL
import json
app = Flask(__name__)
app.config['MYSQL_HOST'] = '127.0.0.1'
app.config['MYSQL_USER'] = 'root'
app.config['MYSQL_PASSWORD'] = 'password'
app.config['MYSQL_DB'] = 'hello_db'
mysql = MySQL(app)

@app.route('/hello')
def index():
   cur = mysql.connection.cursor()
   cur.execute('''SELECT * FROM Users WHERE id=1''')
   row_headers=[x[0] for x in cur.description] #this will extract row headers
   rv = cur.fetchall()
   json_data=[]
   for result in rv:
        json_data.append(dict(zip(row_headers,result)))
   return json.dumps(json_data)

if __name__ == '__main__':
   app.run(debug=True)

In the return statement you can use jsonify instead of json.dumps as suggested by RickLan in the comments.在return语句可以使用jsonify代替json.dumps由RickLan的意见建议。

From your output it seems like you are getting a tuple back?从您的输出中,您似乎得到了一个元组? In which case you should be able to just map it.在这种情况下,您应该能够对其进行映射。

from flask import Flask, jsonify
from flask.ext.mysqldb import MySQL

app = Flask(__name__)
app.config['MYSQL_HOST'] = '127.0.0.1'
app.config['MYSQL_USER'] = 'root'
app.config['MYSQL_PASSWORD'] = 'password'
app.config['MYSQL_DB'] = 'hello_db'
mysql = MySQL(app)

@app.route('/hello')
def index():
   cur = mysql.connection.cursor()
   cur.execute('''SELECT * FROM Users WHERE id=1''')
   rv = cur.fetchall()
   payload = []
   content = {}
   for result in rv:
       content = {'id': result[0], 'username': result[1], 'password': result[2]}
       payload.append(content)
       content = {}
   return jsonify(payload)

if __name__ == '__main__':
   app.run(debug=True)

There is, perhaps, a simpler way to do this: return a dictionary and convert it to JSON.也许有一种更简单的方法来做到这一点:返回一个字典并将其转换为 JSON。

Just pass dictionary=True to the cursor constructor as mentioned in MySQL's documents .只需将dictionary=True传递给MySQL 文档中提到的游标构造函数。

import json
import mysql.connector

db = mysql.connector.connect(host='127.0.0.1',
                             user='admin',
                             passwd='password',
                             db='database',
                             port=3306)

# This line is that you need
cursor = db.cursor(dictionary=True)

name = "Bob"
cursor.execute("SELECT fname, lname FROM table WHERE fname=%s;", (name))

result = cursor.fetchall()

print(f"json: {json.dumps(result)}")

Which will print -哪个将打印 -

json: [{'fname': "Bob", 'lname': "Dole"}, {'fname': "Bob", 'lname': "Marley"}]

(Assuming those Bobs are in the table.) (假设那些 Bobs 在表中。)

Note that types are preserved this way, a good thing, BUT will need to be transformed, parsed, or serialized into a string;请注意,以这种方式保留类型,这是一件好事,但需要将其转换、解析或序列化为字符串; for instance, if there is a date, the SQL query may return a datetime object, which will need to be parsed or serialized depending on your next step.例如,如果有一个日期,SQL 查询可能会返回一个datetime对象,该对象将需要根据您的下一步进行解析或序列化。 A great way to serialize is in this answer .一个很好的序列化方法是在这个答案中

Here's how I resove this issue by setting app.config['MYSQL_CURSORCLASS'] and using jsonify这是我通过设置 app.config['MYSQL_CURSORCLASS'] 并使用 jsonify 来解决这个问题的方法

from flask import Flask, jsonify
from flask_mysqldb import MySQL

app = Flask(__name__)
app.config['MYSQL_HOST'] = '127.0.0.1'
app.config['MYSQL_USER'] = 'root'
app.config['MYSQL_PASSWORD'] = 'password'
app.config['MYSQL_DB'] = 'hello_db'
app.config['MYSQL_CURSORCLASS'] = 'DictCursor' # line of code you require

mysql = MySQL(app)

@app.route('/hello')
def index():
   cur = mysql.connection.cursor()
   cur.execute("SELECT * FROM Users WHERE id=1")
   rv = cur.fetchall()
   return jsonify(rv) # use jsonify here

if __name__ == '__main__':
   app.run(debug=True)

For users using Django, you can import JsonResponse from django.http to do your work.对于使用 Django 的用户,您可以从 django.http 导入JsonResponse来完成您的工作。

Example code snippet:示例代码片段:

from django.http import JsonResponse
from django.db import connection

def home(request):
    with connection.cursor() as cursor:
        cursor.execute("select * from YOUR_TABLE")
        columns = [col[0] for col in cursor.description]
        return JsonResponse([
            dict(zip(columns, row))
            for row in cursor.fetchall()
        ], safe=False)

Note: safe=False has been added to convert the list of dictionaries to Json.注意:添加了safe=False以将字典列表转换为 Json。

If you want to convert more select query results into JSON files, the simple program code below will do it.如果你想将更多的select query results转换成 JSON 文件,下面的简单程序代码就可以做到。 For more details, you have three solutions on github .有关更多详细信息,您在github上有三个解决方案。

Given that a lot has already been clarified.鉴于已经澄清了很多。 Briefly about the methods:简单介绍一下方法:

  • class DateTimeEncoder(JSONEncoder) - encoder to support datetime - doc . class DateTimeEncoder(JSONEncoder) - 支持日期时间的编码器 - doc
  • get_current_date_time - current time to distinguish if working with variable data get_current_date_time - 当前时间以区分是否使用可变数据
  • query_db - Use cursor description to extract row headers, and You get an array of dictionary objects headers:values. query_db - 使用游标描述来提取行标题,并且您会得到一个字典对象 headers:values 的数组。
  • write_json(query_path) - reading SQL and generating JSON in already created output folder write_json(query_path) - 在已创建的output文件夹中读取 SQL 并生成 JSON
  • convertion_mysql - with glob find all files in a directory with extension .sql and calling the described and defined method write_json convertion_mysql - 使用glob查找扩展名为 .sql 的目录中的所有文件,并调用所描述和定义的方法write_json
import json
from json import JSONEncoder
import datetime
import os
import glob

class DateTimeEncoder(JSONEncoder):
        def default(self, obj):
            if isinstance(obj, (datetime.date, datetime.datetime)):
                return obj.isoformat()

def get_current_date_time():
    return datetime.datetime.now().strftime('%a_%d.%b.%Y_%H.%M.%S')

def query_db(query):
    cur = mysql.connection.cursor()
    cur.execute(query)
    r = [dict((cur.description[i][0], value) for i, value in enumerate(row)) for row in cur.fetchall()]
    cur.connection.close()
    return r

def write_json(query_path):
    with open(f"{query_path}", 'r') as f:
        sql = f.read().replace('\n', ' ')
    file_name = os.path.splitext(os.path.basename(f"{query_path}"))[0]
    with open(f"../output/{file_name}_{get_current_date_time()}.json", 'w', encoding='utf-8') as f:
        json.dump(query_db(sql), f, ensure_ascii=False, indent=4, cls=DateTimeEncoder)

def convertion_mysql():
    mysql_query = [f for f in glob.glob("../myqls/*.sql")]
    for sql in mysql_query:
        write_json(sql)

if __name__ == "__main__":
    convertion_mysql()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM