2

If you define a field with blank=True then validation properly allows blank values and if blank=False then blank values raise a validation exception. Usually it's pretty simple, but with JSONField it's possible to have one of 3 different blank values which are: '', [], {}. Essentially, I'd like to only allow {} as the only acceptable blank value. However, blank values are never passed to custom field validators so it seems like it's not possible through standard means.

def validate_dict(value):
    if not isinstance(value, dict):
        raise ValidationError(
            '"%(value)s" is not valid JSON',
            params={'value': value},
        )

class MyModel(models.Model):
    json = JSONField(default=dict, blank=True, validators=[validate_dict])

In the above example, all the "blank" values are immediately seen as valid and validate_dict is never called. If I change blank=True to blank=False then all blank values are immediately seen as invalid and again validate_dict is never called.

I'd like to validate that the stored data is always a dict, but it seems to be impossible to validate that the empty value is a dict only.

Mehdi
  • 717
  • 1
  • 7
  • 21
Tim Tisdall
  • 9,914
  • 3
  • 52
  • 82

1 Answers1

2

I found https://stackoverflow.com/a/56271722/918558 which shows that I can get around the issue by doing the following:

def validate_dict(value):
    if not isinstance(value, dict):
        raise ValidationError(
            '"%(value)s" is not valid JSON',
            params={'value': value},
        )


class DictJSONField(JSONField):
    empty_values = [{}]
    default_validators = [validate_dict]


class MyModel(models.Model):
    json = DictJSONField(default=dict, blank=True)

It's always seems to be that you find the answer immediately after crafting the question in SO. (though I haven't tested it yet)

Tim Tisdall
  • 9,914
  • 3
  • 52
  • 82