## Flask返回指定格式的RESTful json
- 期望的返回格式,同时自动转换需要的内容
``` json
{
"code":0,
"msg":"OK", // 自动封装code 和 msg
"data":[] // flask return 的内容赋值给data
}
```
- 步骤
1. [创建 JSONEncoder ,交由flask app.json_encoder](#1-jsonencoder-flask-app-json_encoder)
2. [创建 APIResponse 定义返回json格式](#2-apiresponse-json-)
3. [创建 api_route 调用 APIResponse 返回指定格式json](#3-api_route-apiresponse-json)
4. [创建异常处理类 APIException](#4-apiexception)
5. [使用,在程序中结合自己写的api_route和JSONEncoder使用](#5-api_route-jsonencoder-)
#### 1. 创建 JSONEncoder ,交由flask app.json_encoder
- JSONEncoder.py
``` python
import datetime
import decimal
import uuid
from flask.json import JSONEncoder as BaseJSONEncoder
import numpy as np
class JSONEncoder(BaseJSONEncoder):
def default(self, o):
if isinstance(o, datetime.datetime):
# 格式化时间
return o.strftime("%Y-%m-%d %H:%M:%S") if o is not None else None
if isinstance(o, datetime.date):
# 格式化日期
return o.strftime('%Y-%m-%d') if o is not None else None
if isinstance(o, decimal.Decimal):
# 格式化高精度数字
return str(o)
if isinstance(o, uuid.UUID):
# 格式化uuid
return str(o)
if isinstance(o, bytes):
# 格式化字节数据
return o.decode("utf-8")
# 其他需要处理的对象转换成可编码成json的对象d
return super(JSONEncoder, self).default(o)
```
#### 2. 创建 APIResponse 定义返回json格式
- APIResponse.py
``` python
class APIResponse():
msg = 'ok'
error = 0
data = {}
def __init__(self, data, msg=None, error=None, header=None):
if msg:
self.msg = msg
self.data = data
def body(self):
body = self.__dict__
body["data"] = self.data
body["msg"] = self.msg
body["code"] = self.error
return body
```
#### 3. 创建 api_route 调用 APIResponse 返回指定格式json
- api_route.py
``` python
from flask import jsonify
from APIResponse import APIResponse
from functools import wraps
def route(bp, *args, **kwargs):
# 路由设置,统一返回格式
# :param bp: 蓝图
# :param args:
# :param kwargs:
# :return:
kwargs.setdefault('strict_slashes', False)
def decorator(f):
@bp.route(*args, **kwargs)
@wraps(f)
def wrapper(*args, **kwargs):
result = f(*args, **kwargs)
base = APIResponse(result)
rv = base.body()
# 响应函数返回整数和浮点型
if isinstance(rv, (int, float,str)):
return jsonify(rv)
# 响应函数返回元组
elif isinstance(rv, tuple):
# 判断是否为多个参数
if len(rv) >= 3:
return jsonify(rv[0]), rv[1], rv[2]
else:
return jsonify(rv[0]), rv[1]
# 响应函数返回字典
elif isinstance(rv, dict):
return jsonify(rv)
# 响应函数返回字节
elif isinstance(rv, bytes):
rv = rv.decode('utf-8')
return jsonify(rv)
else:
return jsonify(rv)
return f
return decorator
```
#### 4. 创建异常处理类 APIException
- APIException.py
``` python
from flask import request, json
from werkzeug.exceptions import HTTPException
class APIException(HTTPException):
code = 500
msg = 'sorry, we make a mistake'
error = 500
def __init__(self, msg=None, error=None, code=None, header=None):
if code:
self.code = code
if msg:
self.msg = msg
if error:
self.code = error
if error:
self.error = error
super(APIException, self).__init__(msg, None)
def get_body(self, environ=None):
body = dict(
msg=self.msg,
code=self.code
)
text = json.dumps(body)
return text
def get_headers(self, environ=None):
return [('Content-Type', 'application/json')]
```
#### 5. 使用,在程序中结合自己写的api_route和JSONEncoder使用
- 入口文件 app.py
- 同时对常见异常进行处理,控制返回指定格式json
``` python
from flask import Flask
from JSONEncoder import JSONEncoder
from api_route import route
app=Flask(__name__)
# 404处理
@app.errorhandler(404)
def not_found(e):
return make_response({'code':404, 'msg':'not found'}, 404)
# 异常处理
@app.errorhandler(Exception)
def framework_error(e):
msg = traceback.format_exc().split("\n")[-2]
error = 500
if isinstance(e, APIException):
msg = e.msg
error = e.error
if error == 500:
app.logger.error('ajax request - error %s' % msg)
app.logger.error(traceback.format_exc())
return APIException(msg=msg, code=error)
@route(app, '/' , methods=['POST', 'GET']) # 使用自己写的route,传入app/blueprint对象使得 Flask能够通过APIResponse处理生成指定格式json
def hello_world():
return {'lists':[0, 1, 2, 3, 4, 5]}
# 异常处理
@route(app,'/error' ,methods=['POST', 'GET'])
def error():
a = 99
b = 0
return a/b # 除0引发异常
app.json_encoder = JSONEncoder # 同时确保返回的内容能够被转换成json
app.run()
```