Flask MySQL JSON 한글

Flask에서 MySQL 접속시 발생한 에러

  • TypeError: Object of type Decimal is not JSON serializable
  • MySQL에서 utf8을 사용하도록 처리했지만 한글 출력 문제 발생
  • jsonify() 및 json.dumps() 문제들
  • JSON에서 객체 대신 배열로 값들이 들어가는 문제
  • DB의 애트리뷰트 순서와 다르게 JSON에서 정렬되는 문제

해결 방법

  • simplejson 설치

    apt-get install libmysqlclient-dev
    pip install simplejson flask-mysqldb

    • simplejson 설치해 두면 자동으로 jsonify에서 사용함
  • 커서로 DictCursor를 사용하도록 지정

    app.config[‘MYSQL_CURSORCLASS’] = ‘DictCursor’

  • JSON에서 sort하지 않도록 지정

    app.config[‘JSON_SORT_KEYS’] = False

  • Header 사용
    • jsonify()는 자체 헤더 포함
    • json.dumps()는 헤더 포함하지 않음
1
2
3
4
5
6
7
8
@app.route("/", methods=["GET"])
def index():
query = 'select * from 테이블 이름'
cur = db.connection.cursor()
cur.execute(query)
r = Response(response=json.dumps(cur.fetchall()))
r.headers["Content-Type"] = "application/json; charset=utf-8"
return r

소스 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
from flask import Flask, jsonify
from flask_mysqldb import MySQL
# mysqlclient, flask-mysqldb, simplejson 설치 필요함
# apt-get install libmysqlclient-dev
# pip install simplejson flask-mysqldb
# simplejson은 설치만 해두면 jsonify에서 사용함

app = Flask(__name__)

app.config['MYSQL_HOST'] = 'localhost'
app.config['MYSQL_USER'] = 'root'
app.config['MYSQL_PASSWORD'] = '패스워드'
app.config['MYSQL_DB'] = '데이터베이스 이름'
app.config['MYSQL_CURSORCLASS'] = 'DictCursor'
app.config['JSON_SORT_KEYS'] = False
db = MySQL(app)


@app.route("/", methods=["GET"])
def index():
query = 'select * from 테이블 이름'
cur = db.connection.cursor()
cur.execute(query)
return jsonify(cur.fetchall())


# @app.route("/", methods=["GET"])
# def index():
# query = 'select * from 테이블 이름'
# cur = db.connection.cursor()
# cur.execute(query)
# r = Response(response=json.dumps(cur.fetchall()))
# r.headers["Content-Type"] = "application/json; charset=utf-8"
# return r


if __name__ == "__main__":
app.run(host='0.0.0.0', port=80, debug=True)

관련 강의

https://colab.research.google.com/drive/1BAbJdJ8O5LH9EIFf9qjf2brTpaPn5iv-
https://bit.ly/2Y5xH7P

https://bwoh.github.io/2021/01/10/dbex/Chap-13-Flask/

Docker로 MySQL 사용시 한글 에러 해결 방법

MySQL(5.7 버전)에서 한글 깨지는 문제 해결 방법

Create Database 및 Create Table에 UTF8 지정

1
2
CREATE DATABASE `testdb` 
default charset=utf8 collate utf8_general_ci;
1
2
3
4
5
6
CREATE TABLE `test` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB
default charset=utf8 collate utf8_general_ci;

Docker로 MySQL 컨테이너 실행 (Windows Power Shell 실행시)

1
2
3
4
5
6
7
8
docker run -d `
--network todo-app --network-alias mysql `
-v todo-mysql-data:/var/lib/mysql `
-e MYSQL_ROOT_PASSWORD=secret `
-e MYSQL_DATABASE=todos `
mysql:5.7 `
--character-set-server=utf8 `
--collation-server=utf8_general_ci

Docker-Compose 사용시 (docker-compose.yml)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
version: "3.8"

services:
mysql:
image: mysql:5.7
volumes:
- todo-mysql-data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: todos
command:
- --character-set-server=utf8
- --collation-server=utf8_general_ci


volumes:
todo-mysql-data: