python-restx / flask-restx

Fork of Flask-RESTPlus: Fully featured framework for fast, easy and documented API development with Flask
https://flask-restx.readthedocs.io/en/latest/
Other
2.16k stars 335 forks source link

Using marshal with required fields for a response #525

Closed PabloCR closed 1 year ago

PabloCR commented 1 year ago

Hey, I'm just looking for some clarity if I'm understanding marshal wrong.

I have created a model with some fields marked as required.

I have a controller with a GET method annotated with @ns.marshall_with(model)

This method gets some data from another datasource, if the data is missing one of the fields marked as required in the model, the marshaled object stills returns 200 with said property and a value of null.

Right here was my first head scratch I would have expected that a required field that was not mapped to throw an error. But I thought, given I'm doing the marshal with an annotation, it is just making sure the returning object has the specified property, no the value. Here is question 1, am I right here? Is this what is happening?

I keep on testing with the assumption above, so I imported 'marshal' and try to marshal the object before the return

my_data = marshal(data_source_object, model)

Again here my understanding was that this time a validation would happen when marshalling and it would raise an exception due to the missing field but then again, it just added the property with null value.

Could somebody clear this one out for me? am I doing this wrong and marshal will not throw errors on missing required fields? and if so, what is a good way to validate this kind of scenarios?

Thanks for any help in advance

peter-doggart commented 1 year ago

flask-restx marshalling is only there to ensure that the JSON you are returning matches that which is defined by the model (and therefore the swagger.json file).

In the instance, if you marshal an object that doesn't contain all fields specified by the model, the marshaller will add the field with either it's specified default value or None if not set (or you can use skip_none to remove these fields). If you marshal an object that contains fields not defined by the model, the marshaller removes them.

Validation of the objects before marshalling is left up to the implementer if it is required. I've never tried, but I think you could probably use model.validate() or something similar, or even just iterating a list of required dictionary fields might be simpler.

If you are dealing with complex large models, then you might want to look at more advanced / recent frameworks like flask-smorest using Marshmallow, which have much more powerful object serialization capabilities.

PabloCR commented 1 year ago

Go it, I was not that far off then. Thank you for your help!