#35642 closed Bug (invalid)
After Upgrading from Django 2.2.28 to Django 3.2.25, JSONField is returning data in string rather than dictionary/list
| Reported by: | Bittu Ray | Owned by: | |
|---|---|---|---|
| Component: | contrib.postgres | Version: | 3.2 | 
| Severity: | Normal | Keywords: | jsonfield, django 3.2 | 
| Cc: | Triage Stage: | Unreviewed | |
| Has patch: | no | Needs documentation: | no | 
| Needs tests: | no | Patch needs improvement: | no | 
| Easy pickings: | no | UI/UX: | no | 
Description
class CustomPatchedJSONFormField(JSONFormField):
    def prepare_value(self, value):
        """
        Exclude returning None in case of {}, returning None makes the field empty when loaded
        from admin instead of returning {},
        which causes an error where empty dict was expected
        """
        if value != {} and value in self.empty_values:
            return None
        elif isinstance(value, str):
            return value
        else:
            return super(CustomPatchedJSONFormField, self).prepare_value(value)
class CustomJSONField(JSONField):
    """
    Overrides
    1. `formfield` to set our custom JSON field as `form_class`
    2. `from_db_value` to return a json from `str`
    """
    def formfield(self, **kwargs):
        defaults = {"form_class": CustomPatchedJSONFormField}
        defaults.update(kwargs)
        return super(JSONField, self).formfield(**defaults)
    def from_db_value(self, value, expression, connection, context=None):
        
        if isinstance(value, str):
            try:
                return json.loads(value)
            except ValueError:
                return value
        return value
My Model 
class MyModel(models.Model):
      field1 = CustomJSONField(default=list)
when I am creating an object with dictionary as input, it's working perfectly fine, but when I am creating the object input as str or json.dumps, the output is also coming in string format rather than python dictionary or list format
for example
MyModel.objects.create(field1={"key1:"value"})
a = MyModel.objects.get(id=1)
print(a.field1)
# It prints - {"key1:"value"}
# It's working fine and I am getting the output in dictionary format
# but when I try this :
MyModel.objects.create(field1='{"key1:"value"}')
a = MyModel.objects.get(id=1)
print(a.field1)
# It prints - '{"key1:"value"}'
# The value of field1 is in string format rather than dictionary format
I am using Postgres as my database and it was working fine till Django 2.2.28
Change History (2)
comment:1 by , 15 months ago
| Resolution: | → invalid | 
|---|---|
| Severity: | Release blocker → Normal | 
| Status: | new → closed | 
comment:2 by , 15 months ago
when I am creating the object input as str or json.dumps, the output is also coming in string format rather than python dictionary or list format
That's the crux of your issue; don't do that. JSON supports storing strings as top level members so if you want objects to be stored pass dict and not their JSON serialized form.
Hello Bittu Ray! Thank you for your ticket. Please note that Django 2.2 and Django 3.2 are no longer supported, so I'll be closing this ticket accordingly. If you can reproduce this issue in the latest Django 5.0, please reopen with detailed instructions on how to reproduce.
The release notes of each version could also help you understand your issue, specifically: https://docs.djangoproject.com/en/5.0/releases/3.1/#jsonfield-for-all-supported-database-backends and https://docs.djangoproject.com/en/5.0/releases/3.1/#deprecated-jsonfield