python - array - Frasco: decorador para verificar el esquema JSON y JSON
json schema generator (1)
Tengo una aplicación de matraz con llamadas que esperan carga JSON. Antes de procesar cada llamada, tengo un proceso de verificación de errores de 2 pasos:
- Asegúrate de que la carga es un JSON válido
- Asegúrate de que la carga útil JSON cumple con un esquema específico
Que se implementa de la siguiente manera:
@app.route(''/activate'', methods=[''POST''])
def activate():
request_id = request.__hash__()
# Assert that the payload is a valid JSON
try:
input = request.json
except BadRequest, e:
msg = "payload must be a valid json"
return jsonify({"error": msg}), 400
# JSON Schema Validation
try:
validate(request.json, app.config[''activate_schema''])
except ValidationError, e:
return jsonify({"error": e.message}), 400
Como este código está duplicado en muchas llamadas, me pregunto si puedo moverlo elegantemente a un decorador, algo en la forma de:
@validate_json
@validate_schema(schema=app.config[''activate_schema''])
@app.route(''/activate'', methods=[''POST''])
def activate():
....
El problema es que el argumento de request
es implícito: puedo referirme a él dentro de la función, pero no es un parámetro para él. Por lo tanto, no estoy seguro de cómo usarlo en el decorador.
¿Cómo puedo implementar las comprobaciones de validación con los decoradores de Python?
Simplemente use el contexto de request
global en su decorador. Está disponible durante cualquier solicitud .
from functools import wraps
from flask import (
current_app,
jsonify,
request,
)
def validate_json(f):
@wraps(f)
def wrapper(*args, **kw):
try:
request.json
except BadRequest, e:
msg = "payload must be a valid json"
return jsonify({"error": msg}), 400
return f(*args, **kw)
return wrapper
def validate_schema(schema_name):
def decorator(f):
@wraps(f)
def wrapper(*args, **kw):
try:
validate(request.json, current_app.config[schema_name])
except ValidationError, e:
return jsonify({"error": e.message}), 400
return f(*args, **kw)
return wrapper
return decorator
Aplique estos decoradores antes de aplicar el decorador @route
; Desea registrar la función envuelta, no la función original para la ruta:
@app.route(''/activate'', methods=[''POST''])
@validate_json
@validate_schema(''activate_schema'')
def activate():
input = request.json