Help us understand the problem. What is going on with this article?

mysqlから持って来たデータをjsonで返すapiをflaskで作る

More than 1 year has passed since last update.

動機

pythonのflaskを使って、MySQLから持って来たデータをjson形式で返すAPIを作りたい

はまったところ

1.MySQLから持って来たデータをどうやってjson形式(≒辞書型)にするか
2.辞書型で取り出した後に遭遇した TypeError: Object of type 'datetime' is not JSON serializable というエラー

解決策

1.普通にデータを取得するとタプルで返ってくるが、下記のようにdictionary=Trueを渡すと辞書型で返ってくる。

query = 'SELECT * FROM tablename WHERE dataid = ' + str(dataid)
cursor = conn.cursor(dictionary=True)
cursor.execute(query)

2.TypeError: Object of type 'datetime' is not JSON serializableの対策

[Python] dateやdatetimeをjson.dumpでエラーなく出力する

ここを参考に、下記のような処理を挟んだ。

def json_serial(obj):
    if isinstance(obj, (datetime, date)):
        return obj.isoformat()
    elif isinstance(obj, timedelta):
        return str(obj)
    raise TypeError("Type %s not serializable" % type(obj))

mysqlの結果がdatetimeだったりすると見出しにあるエラーが出るので、個別に処理している。
また、timedeltaについてはdatetimeと同様の処理だと下記のエラーが出るので上のソースでは別処理として追記している。
'datetime.timedelta' object has no attribute 'isoformat'

全体のソース

下記は例です

from flask import Flask, send_file, make_response, jsonify
import requests
from datetime import datetime, date, timedelta
import json
import mysql.connector

app = Flask(__name__, static_folder=None)

def json_serial(obj):
    if isinstance(obj, (datetime, date)):
        return obj.isoformat()
    elif isinstance(obj, timedelta):
        return str(obj)
    raise TypeError("Type %s not serializable" % type(obj))

@app.route('/data/<string:dataid>', methods=['GET'])
def getData(param, dataid):
    response_data = {}

    conn = mysql.connector.connect(
        host='hostname',
        port=3306,
        user='dbuser',
        password='dbpass',
        database='dbname',
    )

    query = 'SELECT * FROM tablename WHERE dataid = ' + str(dataid)
    cursor = conn.cursor(dictionary=True)
    cursor.execute(query)
    data = cursor.fetchall()
    conn.close()

    response_data["body"] = data
    response_data["status"] = "200"

    return make_response(json.dumps(response_data, default=json_serial))

# main
if __name__ == "__main__":
    print(app.url_map)
    app.run(host='localhost', port=5000)

参考にしたページ

[Python] dateやdatetimeをjson.dumpでエラーなく出力する

追記:MySQLdbを使う場合

事前に pip install mysqlclient でインストールをしておいて、下記で行けるようです。

connection = MySQLdb.connect(
        host='localhost', user='root', passwd='testpass', db='sample_db', charset='utf8')
    cursor = connection.cursor(MySQLdb.cursors.DictCursor)
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away