简体   繁体   English

flask:如何对请求 JSON 和 JSON 架构进行验证?

[英]flask: how to make validation on Request JSON and JSON schema?

In flask-restplus API, I need to make validation on request JSON data where I already defined request body schema with api.model . In flask-restplus API, I need to make validation on request JSON data where I already defined request body schema with api.model . Basically I want to pass input JSON data to API function where I have to validate input JSON data before using API function. Basically I want to pass input JSON data to API function where I have to validate input JSON data before using API function. To do so, I used RequestParser for doing this task, but the API function was expecting proper JSON data as parameters after request JSON is validated and parsed. To do so, I used RequestParser for doing this task, but the API function was expecting proper JSON data as parameters after request JSON is validated and parsed. To do request JSON validation, first I have to parse received input JSON data, parse its JSON body, validate each then reconstructs it as JSON object, and pass to the API function. To do request JSON validation, first I have to parse received input JSON data, parse its JSON body, validate each then reconstructs it as JSON object, and pass to the API function. Is there any easier way to do this?有没有更简单的方法来做到这一点?

input JSON data输入 JSON 数据

{
  "body": {
    "gender": "M",
    "PCT": {
      "value": 12,
      "device": "roche_cobas"
    },
    "IL6": {
      "value": 12,
      "device": "roche_cobas"
    },
    "CRP": {
      "value": 12,
      "device": "roche_cobas"
    }
  }
}

my current attempt in flask我目前在 flask 中的尝试

from flask_restplus import Api, Namespace, Resource, fields, reqparse, inputs
from flask import Flask, request, make_response, Response, jsonify

app = Flask(__name__)
api = Api(app)
ns = Namespace('')

feature = api.model('feature', {
    'value': fields.Integer(required=True),
    'time': fields.Date(required=True)
})

features = api.model('featureList', {
    'age': fields.String,
    'gender': fields.String(required=True),
    'time': fields.Date,
    'features': fields.List(fields.Nested(feature, required=True))
    })

@ns.route('/hello')
class helloResource(Resource):
    @ns.expect(features)
    def post(self):
        json_dict = request.json  ## get input JSON data
        ## need to parse json_dict to validate expected argument in JSON body
        root_parser = reqparse.RequestParser()
        root_parser.add_argument('body', type=dict)
        root_args = root_parser.parse_args()

        jsbody_parser = reqparse.RequestParser()
        jsbody_parser.add_argument('age', type=dict, location = ('body',))
        jsbody_parser.add_argument('gender', type=dict, location=('body',))
        ## IL6, CRP could be something else, how to use **kwargs here
        jsbody_parser.add_argument('IL6', type=dict, location=('body',))
        jsbody_parser.add_argument('PCT', type=dict, location=('body',))
        jsbody_parser.add_argument('CRP', type=dict, location=('body',))
        jsbody_parser = jsbody_parser.parse_args(req=root_args)

        ## after validate each argument on input JSON request body, all needs to be constructed as JSON data
        json_data = json.dumps(jsonify(jsbody_parser))   ## how can I get JSON again from jsbody_parser
        func_output = my_funcs(json_data)
        rest = make_response(jsonify(str(func_output)), 200)
        return rest

if __name__ == '__main__':
    api.add_namespace(ns) 
    app.run(debug=True)

update: dummy api function更新:虚拟 api function

Here is dummy function that expecting json data after validation:这是虚拟 function 验证后期望 json 数据:

import json
def my_funcs(json_data):
    a =json.loads(json_data)
    for k,v in a.iteritems():
           print k,v
    return jsonify(a)

current output of above attempt :上述尝试的当前 output

I have this on response body:我在响应正文上有这个:

{
  "errors": {
    "gender": "'gender' is a required property"
  },
  "message": "Input payload validation failed"
}

obviously, request JSON input is not handled and not validated in my attempt.显然,请求 JSON 输入在我的尝试中未处理且未验证。 I think I have to pass json_dict to RequestParser object, but still can't validate request JSON here.我想我必须将json_dict传递给 RequestParser object,但仍然无法在此处验证请求 JSON。 how to make this happen?如何做到这一点?

I have to validate expected arguments from JSON body, after validation, I want to construct JSON body that gonna be used as a parameter for API function. I have to validate expected arguments from JSON body, after validation, I want to construct JSON body that gonna be used as a parameter for API function. How can I make this happen?我怎样才能做到这一点? any workaround to achieve this?任何解决方法来实现这一点?

parsed JSON must pass to my_funcs解析的 JSON 必须传递给my_funcs

in my post, request JSON data should be parsed, such as age , gender should be validated as expected arguments in the request JSON, then jsonify added arguments as JSON and pass the my_funcs . in my post, request JSON data should be parsed, such as age , gender should be validated as expected arguments in the request JSON, then jsonify added arguments as JSON and pass the my_funcs . how to make this happen easily in fl如何在佛罗里达州轻松做到这一点

I want to make sure flask should parse JSON body and add arguments as it expected, otherwise throw up error.我想确保 flask 应该解析 JSON 正文并按预期添加 arguments ,否则会抛出错误。 for example:例如:

{
      "body": {
        "car": "M",
        "PCT": {
          "value": 12,
          "device": "roche_cobas"
        },
        "IL6": {
          "device": "roche_cobas"
        },
        "CRP": {
          "value": 12
        }
      }
    }

if I give JSON data like above for making POST request to a server endpoint, it should give the error.如果我像上面一样给 JSON 数据以向服务器端点发出 POST 请求,它应该给出错误。 How to make this happen?如何做到这一点? how to validate POST request JSON for flask API call?如何验证 flask API 调用的 POST 请求 JSON?

As I tried to convey in our conversation it appears you are after a serilzation and deserilization tool.正如我试图在我们的谈话中传达的那样,您似乎正在使用序列化和反序列化工具。 I have found Marshmallow to be an exceptional tool for this (it is not the only one).我发现 Marshmallow 是一个特殊的工具(它不是唯一的)。 Here's a working example of using Marshmallow to validate a request body, converting the validated data back to a JSON string and passing it to a function for manipulation, and returning a response with JSON data:这是一个使用 Marshmallow 验证请求正文的工作示例,将验证的数据转换回 JSON 字符串并将其传递给 function 进行操作,并返回带有 Z0ECD11C1D7A287401FZD148A 数据的响应:

from json import dumps, loads
from flask import Flask, jsonify, request
from marshmallow import Schema, fields, ValidationError

class BaseSchema(Schema):
    age = fields.Integer(required=True)
    gender = fields.String(required=True)

class ExtendedSchema(BaseSchema):
    # have a look at the examples in the Marshmallow docs for more complex data structures, such as nested fields.
    IL6 = fields.String()
    PCT = fields.String()
    CRP = fields.String()

def my_func(json_str:str):
    """ Your Function that Requires JSON string"""

    a_dict = loads(json_str)

    return a_dict

app = Flask(__name__)

@app.route('/base', methods=["POST"])
def base():
    # Get Request body from JSON
    request_data = request.json
    schema = BaseSchema()
    try:
        # Validate request body against schema data types
        result = schema.load(request_data)
    except ValidationError as err:
        # Return a nice message if validation fails
        return jsonify(err.messages), 400

    # Convert request body back to JSON str
    data_now_json_str = dumps(result)

    response_data = my_func(data_now_json_str)

    # Send data back as JSON
    return jsonify(response_data), 200


@app.route('/extended', methods=["POST"])
def extended():
    """ Same as base function but with more fields in Schema """
    request_data = request.json
    schema = ExtendedSchema()
    try:
        result = schema.load(request_data)
    except ValidationError as err:
        return jsonify(err.messages), 400

    data_now_json_str = dumps(result)

    response_data = my_func(data_now_json_str)

    return jsonify(response_data), 200

Here's some quick tests to show validation, as well as extending the fields in your request body:以下是一些显示验证的快速测试,以及扩展请求正文中的字段:

import requests
# Request fails validation
base_data = {
    'age': 42,
    }
r1 = requests.post('http://127.0.0.1:5000/base', json=base_data)
print(r1.content)

# Request passes validation
base_data = {
    'age': 42,
    'gender': 'hobbit'
    }
r2 = requests.post('http://127.0.0.1:5000/base', json=base_data)
print(r2.content)

# Request with extended properties
extended_data = {
    'age': 42,
    'gender': 'hobbit',
    'IL6': 'Five',
    'PCT': 'Four',
    'CRP': 'Three'}

r3 = requests.post('http://127.0.0.1:5000/extended', json=extended_data)
print(r3.content)

Hope this helps gets you where you're going.希望这可以帮助您到达目的地。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM