# Django 3.1 JSONField and raw SQL JSON decoding

**URL:** <https://forum.djangoproject.com/t/django-3-1-jsonfield-and-raw-sql-json-decoding/4976>\
**Category:** Using Django\
**Created:** [October 27, 2020, 8:39pm UTC](https://forum.djangoproject.com/t/django-3-1-jsonfield-and-raw-sql-json-decoding/4976 "2020-10-27T20:39:56Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Amertz08](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/amertz08/32/2314_2.png) [@Amertz08](https://forum.djangoproject.com/u/Amertz08)\
**Post date:** [October 27, 2020, 8:39pm UTC](https://forum.djangoproject.com/t/django-3-1-jsonfield-and-raw-sql-json-decoding/4976/1 "2020-10-27T20:39:56Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [October 27, 2020, 9:55pm UTC](https://forum.djangoproject.com/t/django-3-1-jsonfield-and-raw-sql-json-decoding/4976/2 "2020-10-27T21:55:15Z")

</div>

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. )

---

<div class="post-metadata">

**Author:** ![Amertz08](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/amertz08/32/2314_2.png) [@Amertz08](https://forum.djangoproject.com/u/Amertz08)\
**Post date:** [October 27, 2020, 11:07pm UTC](https://forum.djangoproject.com/t/django-3-1-jsonfield-and-raw-sql-json-decoding/4976/3 "2020-10-27T23:07:16Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![michalpleszczynski](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/michalpleszczynski/32/3490_2.png) [@michalpleszczynski](https://forum.djangoproject.com/u/michalpleszczynski)\
**Post date:** [February 13, 2021, 1:52pm UTC](https://forum.djangoproject.com/t/django-3-1-jsonfield-and-raw-sql-json-decoding/4976/4 "2021-02-13T13:52:52Z")

</div>

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](https://code.djangoproject.com/ticket/31991)

---

<div class="post-metadata">

**Author:** ![ropraet](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/ropraet/32/4415_2.png) [@ropraet](https://forum.djangoproject.com/u/ropraet)\
**Post date:** [May 3, 2021, 5:23am UTC](https://forum.djangoproject.com/t/django-3-1-jsonfield-and-raw-sql-json-decoding/4976/5 "2021-05-03T05:23:14Z")

</div>

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

> SELECT  
> vs.branding-\>‘description’ as venue\_\_description,  
> vs.branding-\>‘main\_color’ as venue\_\_main\_color  
> FROM  
> …

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?
