動機
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)