3

Environment:

  • Django 1.9.10
  • psycopg2 2.6.2
  • PostgreSQL 9.5.4 installed via Homebrew on macOS Sierra
  • Python 3.5.2 installed via Homebrew

Example model:

from django.db import models
from django.contrib.postgres.fields import JSONField


class Foo(models.Model):
    data = JSONField()

When I try to create an object, everything works as expected:

from myapp.models import Foo
x = Foo()
x.data = {'some key': 'some value'}
x.save()

However, when I try to retrieve that data, the value of the .data attribute is a string:

from myapp.models import Foo
x = Foo.objects.order_by('-id')[0]
# returns "{'some key': 'some value'}"
x.data
# returns <class 'str'>
type(x.data)

My question: how do I get back the dict so I can manipulate data within the JSON field?

EDIT: Using json.loads() fails because the property names and values are enclosed in single quotes rather than double quotes:

import json
json.loads(x.data)
# JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)

I can use eval(), but that's obviously extremely dangerous.

5
  • 1
    Surely you would use json.loads() rather than eval. Commented Oct 31, 2016 at 18:37
  • You could do use json.loads() to turn that string into the dict you want, but that's very odd. I have an application which uses JSONField and this does not happen. Also, if that was the expected behaviour, there wouldn't be much difference between using JSONField or TextField for example. Are you sure the object you are retrieving is exactly the same that you saved with x.data = {'some key': 'some value'}? Commented Oct 31, 2016 at 18:37
  • @lucasnadalutti the table was empty before I ran this example, so it's guaranteed to be the right object because it's the only object. Also, see the latest edit for why json.loads() isn't working. Commented Oct 31, 2016 at 18:42
  • 1
    As lucas says, this shouldn't happen. Are you sure the data you originally passed was really a dict, not a string? Commented Oct 31, 2016 at 18:43
  • @DanielRoseman I think you're right. I think Django-rest-framework is screwing me up. Let me try something... Commented Oct 31, 2016 at 18:48

1 Answer 1

2

It turns out that the custom DRF serializer I had written to create this field (spawning from actions taken by a POST to another model's detail_route) was using DRF's CharField rather than JSONField. Whoops!

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.