2010-02-11 11 views
34

Come può essere che questo errore è stato sollevato? Sono entrato in questo modo:Django: "TypeError: [] non è serializzabile in JSON" Perché?

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

e ottenuto che l'errore (perché self.items è stato un set di query vuota (Django)

ma poi,

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

funzionato benissimo (che almeno dimostra che il messaggio di errore non ha valore)

È perché il set di query definisce repr() e restituisce '[]' come stringa quando è vuoto o qualcosa g ridicolo come quello?

+3

Perché si sta definendo una funzione con lo stesso nome di un modulo che si sta utilizzando? –

+0

@gnibbler Non è una funzione. È un metodo e lo sto usando come @property (non incluso nel mio esempio). – orokusaki

+3

Mi piace ripensare a quanto ero compiaciuto, '... l'errore era idiota. – orokusaki

risposta

54

I set di query non sono serializzabili immediatamente. Se si prova list(self.items) anziché solo self.items, questo dovrebbe funzionare a condizione che gli elementi stessi siano serializzabili con JSON.

Aggiornamento: Solleverà un'eccezione anche se non è vuota. Non penso che sarà accettato come un bug di Django, anche se ovviamente puoi provarci; la risposta più semplice è forzare la valutazione usando list(qs), come ho già detto.

+1

+1. Questa è la risposta. Si sta usando la lista (queryset) per forzare la valutazione del queryset subito. I dati sottostanti, sotto forma di elenco, sono serializzabili; il queryset in sé non lo è. http://docs.djangoproject.com/en/dev/ref/models/querysets/#id1 – cethegeek

+2

Buona risposta. Grazie. A proposito, sembra un insetto. Ho intenzione di iniziare un biglietto per questo. I serializzatori di Django sono pensati per serializzare i queryset di Django. Se solleva un'eccezione quando è vuota, è un bug. – orokusaki

+1

@orokusaki, questo non mi sembra un problema. A volte vuoi oggetti. A volte vuoi stringhe. Django ti lascia scegliere. Ecco un'alternativa più pitoniosa che funziona per me, per tutti i campi di Django: '[str (obj) for obj in Model.objects.values ​​()]' [vedi sotto] (http://stackoverflow.com/a/14653384/ 623.735) – hobs

5

Questo è molto frustrante. La serializzazione di Django si lamenta di tutto ciò che non è un set di query e json.dumps si lamenta degli oggetti dal supporto ORM di Django.

>>> 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' 
4

Come Vinay sottolineato, anche se si esegue il cast a un elenco, serializzazione spesso non riesce ancora. Per me, la serializzazione non riesce sugli elementi DateTimeField (oggetti datetime.datetime), anche se chiedo uno ValuesQuerySet (elenco-like) con .values(). La soluzione per me era una comprensione semplice.

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

Nel tuo caso, che sarebbe

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

La magia del str salva la situazione. Il dispositivo integrato repr può anche essere utile se avete bisogno di informazioni sul tipo di oggetto nella vostra serializzazione.

Problemi correlati