I want to make a custom field when making an API model and validate that it is either a string or boolean or a list
I have tried
class CustomField(fields.Raw):
__schema_type__ = ["String", "Boolean", "List"]
__schema_example__ = "string or boolean or list"
def format(self, value):
if isinstance(value, str) or isinstance(value, bool) or isinstance(value, list):
return value
else:
raise fields.MarshallingError(
"Invalid type. Allowed types: str, bool, or list."
)
but get the following error when trying to use it.
jsonschema.exceptions.UnknownType: Unknown type 'String' for validator with schema:
{'description': 'Value for the name type of foo',
'example': 'string or boolean or list',
'type': ['String', 'Boolean', 'List']}
I have also tried
class StringOrBooleanOrList(fields.Raw):
"""
Marshal a value as a string or list.
"""
def validate(self, value):
if isinstance(value, str):
return value
elif isinstance(value, list):
return value
elif isinstance(value, bool):
return value
else:
raise ValidationError(
"Invalid input type. Must be a string or list or boolean"
)
With that, strings do not work at all I get the validation error saying
string value must be valid JSON
With lists and booleans it passes through but then I get an error from the API
{
"errors": {
"foo.0.value": "['bar'] is not of type 'object'"
},
"message": "Input payload validation failed"
}
What is the correct way of achieving this in Flask restx?
Fixed it
To do what I wanted I did
class StringOrBooleanOrList(fields.Raw):
__schema_type__ = ["string", "array", "boolean"]
__schema_example__ = "'hello_word' or ['10.0.1.0/24'] or False"
the schema_type is important. You don't put stuff in python terms but in JSON terms.
Hence if you try List, it won't work because JSON only has the following types
an "array" is basically a python list so instead of list, we can use array
And to use this custom field, it's fairly straightforward, instead of field.whatever, you use the class you defined earlier (in this case StringOrBooleanOrList)
example_model = api.model(
"ModelName",
{
"value": StringOrBooleanOrList(),
},
)