Django 3.1 JSONField and raw SQL JSON decoding

I’m migrating our 2.2.X apps to 3.1.2 and I am seeing JSON fields coming back as strings when they had previous came back as python dictionaries. This is happening on both model queries as well as raw SQL queries.

The models were changed to use django.db.models.JSONField from django.contrib.postgres.fields.JSONField. There does not appear to be any documentation indicating that we needed to make any other changes than this. I would have expected this to be sufficient in order to continue the same behavior.

On the raw SQL queries I’m not really sure what is happening. No changes have been made so I would have expected them to still be coming back as a dictionary.

I don’t have any specific ideas, just a couple things I’m curious about…

Did you do a makemigrations / migrate?

Is the underlying database column of type json or is it jsonb?

(I have no specific knowledge as to whether or not either of these are relevant. )

This was happening on any database query. I believe the underlying columns are jsonb

Here is a bug report for this, apparently that’s how it’s going to work from now on: #31991 (QuerySet.raw() method returns string instead of dict for JSONField().) – Django

I was also having some raw SQL queries getting data from jsonb fields like this:

vs.branding->‘description’ as venue__description,
vs.branding->‘main_color’ as venue__main_color

but Django is from version 3.1 converting the integers to strings, and is double quoting the strings.

I am retrieving the data with:

desc = cursor.description
return [dict(zip([col[0] for col in desc], row)) for row in cursor.fetchall()]

How can I fix this?