JSON Encoding with Django adding extra \\ characters
I'm trying to create a function that will convert a dictionary containing a message and a Django model instance into JSON, that I can pass back to the client. For example, I have the model Test defined in models.py.
from django.db import models
class Test(models.Model):
test_field = models.CharField(max_length=40)
I've defined this extension of the simplejson JSONEncoder based on the this stackoverflow question:
from django.core.serializers import serialize
from django.utils.simplejson import dumps, loads, JSONEncoder
from django.db.models.query import QuerySet
from django.db import models
from django.utils.functional import curry
class DjangoJSONEncoder(JSONEncoder):
def default(self, obj):
if isinstance(obj, QuerySet):
# `default` must return a python serializable
# structure, the easiest way is to load the JSON
# string produced by `serialize` and return it
return loads(serialize('json', obj))
if isinstance(obj, models.Model):
#do the same as above by making it a queryset first
set_obj = [obj]
set_str = serialize('json', set_obj)
#eliminate brackets in the beginning and the end
str_obj = set_str[1:len(set_str)-2]
return str_obj
return JSONEncoder.default(self,obj)
# partial function, we can now use dumps(my_dict) instead
# of dumps(my_dict, cls=DjangoJSONEncoder)
dumps = curry(dumps, cls=DjangoJSONEncoder)
Then I go about creating an instance of this along with a status message:
t = Test(test_field="hello")
d = {"entry": t, "message": "Congratulations"}
json = dumps(d)
The contents of json are:
{"entry": "{\\"pk\\": null, \\"model\\": \\"hours.test\\", \\"fields\\": {\\"test_field\\": \\"hello\\"}", "message": "Congratulations"}
Which is basically what I want except for all the extra \\
character开发者_如何转开发s. Why are these being inserted into the json? How can I modify my DjangoJSONEncoder so it doesn't insert the \ characters?
NOTE
If I just encode the model instance manually I don't get all the extra \\
characters.
s = serialize('json', [t])
s[1:len(s)-2]
This outputs:
{"pk": null, "model": "hours.test", "fields": {"test_field": "hello"}
EDIT
Based on the advice of Daniel Roseman and Leopd I modified the DjangoJSONEncoder class to the following:
class DjangoJSONEncoder(JSONEncoder):
def default(self, obj):
if isinstance(obj, QuerySet):
# `default` must return a python serializable
# structure, the easiest way is to load the JSON
# string produced by `serialize` and return it
return loads(serialize('python', obj))
if isinstance(obj, models.Model):
#do the same as above by making it a list first
return serialize('python', [obj])[0]
return JSONEncoder.default(self,obj)
Your logic is wrong, unfortunately. Your "easiest way", as you state, returns a string - but you don't want a string at that point, you want a dictionary. You end up serializing a string within a string, hence the extra quotes which need to be escaped.
Luckily, one of the format options for the serialize
function is python
- which "serializes" the queryset to a Python dictionary. So you just need:
return serialize('python', obj))
You're serializing your Test
model object into a JSON string, and then the entry
field in d
is the string, being serialized, not the data structure.
精彩评论