36

How can this be that this error was raised? I entered this:

def json(self):
    return json.dumps(
        {
            'items': self.items
        }
    )

and got that error (because self.items was an empty queryset (Django)

but then,

def json(self):
    return json.dumps(
        {
            'items': []  # Pass in empty list to prove that the error was idiotic.
        }
    )

worked fine (which at least proves that the error message is worthless)

Is this because the queryset defines repr() and returns '[]' as a string when it's empty or something ridiculous like that?

3
  • 3
    Why are you defining a function with the same name as a module you are using? Commented Feb 11, 2010 at 8:06
  • @gnibbler It's not a function. It's a method and I'm using it as a @property (didn't include that in my example). Commented Feb 11, 2010 at 8:10
  • 3
    I love looking back at how smug I was, ...the error was idiotic. Commented Nov 15, 2013 at 15:44

3 Answers 3

60

Querysets are not serializable out-of-the-box. If you try list(self.items) instead of just self.items, that should work as long as the items themselves are JSON-serializable.

Update: It will raise an exception even if it isn't empty. I don't think it'll be accepted as a Django bug, though of course you can try; the simplest answer is to force evaluation using list(qs), as I've already said.

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

3 Comments

+1. This is the answer. You are using list(queryset) to force the queryset to be evaluated right away. The underlying data, in the form of a list, is serializable; the queryset itself is not. docs.djangoproject.com/en/dev/ref/models/querysets/#id1
Good answer. Thanks. BTW, This seems like a bug. I'm going to start a ticket for it. Django's serializers are meant for serializing Django querysets. If it raises an exception when it's empty, that's a bug.
@orokusaki, this doesn't feel like a bug to me. Sometimes you want objects. Sometimes you want strings. Django lets you chose. Here's a more pythonic alternative that works for me, for all Django fields: [str(obj) for obj in Model.objects.values()] see below
6

This is very frustrating. Django's serialization complains about everything that isn't a query set and json.dumps complains about objects from Django's ORM support.

>>> from cluster.models import Account
>>> import json
>>> json.dumps(Account.objects.all()[0])
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/__init__.py", line 231, in dumps
    return _default_encoder.encode(obj)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/encoder.py", line 201, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/encoder.py", line 264, in iterencode
    return _iterencode(o, 0)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/encoder.py", line 178, in default
    raise TypeError(repr(o) + " is not JSON serializable")
TypeError: <Account: 9de5-2653-000d-81a3 => [email protected]> is not JSON serializable

Versus

>>> serializers.serialize("json", [clusters])
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/core/serializers/__init__.py", line 91, in serialize
    s.serialize(queryset, **options)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/core/serializers/base.py", line 41, in serialize
    for field in obj._meta.local_fields:
AttributeError: 'QuerySet' object has no attribute '_meta'

Comments

4

As Vinay pointed out, even if you cast to a list, serialization often still fails. For me, serialization fails on DateTimeField elements (datetime.datetime objects), even if I ask for a ValuesQuerySet (list-like) with .values(). The solution for me was a simple comprehension.

json.dumps([str(obj) for obj in Model.objects.values()]);

In your case, that would be

return json.dumps({k: str(v) for k, v in self.__dict__.items()})

The magic of str saves the day. The repr built-in may also be helpful if you need object type information in your serialization.

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.