Bud
Bud

Reputation: 1491

Django Rest Framework JSON serializer field failing validation with required=False and no default?

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,

Upvotes: 2

Views: 8945

Answers (4)

Bud
Bud

Reputation: 1491

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.

Upvotes: 2

Sam Sunde
Sam Sunde

Reputation: 151

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.

Upvotes: 3

Amrit
Amrit

Reputation: 2175

you can use syntax something like...

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

        allow_empty_file=True,required=False
    )

Upvotes: 0

Linovia
Linovia

Reputation: 20966

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.

Upvotes: 5

Related Questions