1
votes

How can I set required to be false for a django rest framework JSON serializer field? It seems to be enforcing validation regardless of the required flag:

serializer field

results = serializers.JSONField(required=False, label='Result')

model field

results = models.TextField(blank=True, default="")

But when I submit the form with a blank input, I get:

"results": [
    "Value must be valid JSON."
],

I've also tried changing the model default to {} in both the model field and the serializer field, but have the same response.

UPDATE

Thanks to @Linovia for pointing out that "The required flag does mean that the serializer will not complain if that field isn't present"

After some digging, it looks like DRF is setting a default value of null on the input, which then is caught as invalid... How can I override this, as the serializer "default" attribute doesn't seem to have any effect.

 "results": null,
4
in models.textfield use null=trueDarshan
@Darshan it is a bad idea you don't need null values in a TextField, blank=True is enough.Ivan Semochkin
You don't need a default value like empty string, because blank=True do it for you. It is actually strange logic, why you need JSONField on top of TextField? you can always save JSON string in a plain text. If you use postgres and want binary format then use JSONField in your model. But your code should work, can you add model and serializer in question.Ivan Semochkin

4 Answers

5
votes

The required flag does mean that the serializer will not complain if that field isn't present. However, if it is present, it will follow the validation process. It doesn't mean at all that it will be discarded if it doesn't validate.

3
votes

This appears to be an issue with DRF's empty class (used "to represent no data being provided for a given input or output value). The empty value for a JSONField is not json serializable, so you see

"results": [
    "Value must be valid JSON."
],

To fix this, I overrode DRF's JSONField with my own NullableJSONField

from rest_framework.fields import empty

class NullableJSONField(serializers.JSONField):

    def get_value(self, dictionary):
        result = super().get_value(dictionary)
        if result is empty:
            return None
        return result

and added allow_null=True to the field in the serializer

json_blob = NullableJSONField(required=False, allow_null=True)

The issue with this fix is that the json_blob field is then serialized with None in the response. (e.g. "json_blob": {})

I hope this resolves your issue, and I will post an update if I find a solution that complete removes this field from the response when it is not input.

1
votes

For future reference, one way to successfully and quickly implement this is using the initial keyword on the serializer, which will save an empty dict to the model instance (ensure you have coupled this with a django JSONField in the model definition itself)

serializer:

results = serializers.JSONField(required=False, initial=dict)

model:

results = JSONField(default=dict)

The browsable api will render with {} as the initial value, which you may or may not choose to modify.

0
votes

you can use syntax something like...

class DetailSerializer(serializers.ModelSerializer):
results = ResultSerializer(

        allow_empty_file=True,required=False
    )