flask-restx icon indicating copy to clipboard operation
flask-restx copied to clipboard

Value of different types (e.g., str, list)

Open thanasissdr opened this issue 1 year ago • 2 comments

It seems swagger cannot properly handle the JSON payload and I've been wondering if it's my implementation or there's something wrong. I have attached a MWE to demonstrate part of the issue I have been facing and it is mainly associated with the fact that a value of a key could be of different types, e.g. str or list (that's why in the following example I have used fields.Raw)

from flask_restx import Api, fields, Resource
from flask import Flask, request, jsonify


app = Flask(__name__)
api = Api(app, doc="/swagger")


@app.route("/hello_world", methods=["POST"])
def hello_world():
    payload = request.get_json()

    return jsonify(payload)


filter_component = api.model(
    "FilterComponent",
    {
        "variable": fields.String(required=True),
        "operator": fields.String(required=True),
        "value": fields.Raw(required=True),
    },
)

hello_world_payload = api.model(
    "HelloWorldPayload",
    {
        "filters": fields.List(
            fields.Nested(filter_component, required=True), required=True
        )
    },
)


@api.route("/hello_world")
class HelloWorldResource(Resource):
    @api.expect(hello_world_payload)
    def post(self):
        pass


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

If I go to swagger and try out the endpoint with the following endpoint:


{
  "filters": [
    {
      "variable": "name",
      "operator": "eq",
      "value": ["Bob"]
    }
  ]
}

everything seems to work as expected and get the expected output:

functional

However, if I use the following payload:


{
  "filters": [
    {
      "variable": "name",
      "operator": "eq",
      "value": "Bob"
    }
  ]
}

when I hit the execute button, I don't seem to get anything back.

Expected output:


{
  "filters": [
    {
      "operator": "eq",
      "value": "Bob",
      "variable": "name"
    }
  ]
}

I'm not sure if this is a bug or no, so I have set this as a question. Please feel free to ask if anything else is needed.

python version: 3.11.5 flask version: 2.3.3 flask-restx version: 1.1.0

thanasissdr avatar Sep 23 '23 16:09 thanasissdr

Having a look at the swagger.json that gets generated by your example, the error is caused by the fact that when using fields.Raw the default data type is object and in example two, you are passing a string which is not an object as far as swagger is concerned.

I don't think there is any neat way to allow flask-restx / Swagger 2.0 to allow you to have multiple data types. My suggestion would be to always pass a list of strings, even if you only have one value, so you have a fixed data type, and then use fields.String instead.

peter-doggart avatar Sep 25 '23 09:09 peter-doggart

@peter-doggart Thanks for the insight! This is what I have seen, as well, however I am not sure If I can apply your suggestion as is, since there might be objects of different types, i.e., floats, integers, strings. I was hoping flask-restx could support multiple data types.

thanasissdr avatar Sep 25 '23 15:09 thanasissdr