Reputation: 25585
I'm using JSONfield to store some JSON formated data in one field. But when I go to my API which build with help of tasty-pie it returns that jason as a string not a nested JSON as I expected.
class Item(models.Model):
user = models.ForeignKey(User)
body = JSONField(max_length=1024)
class ItemResource(ModelResource):
authorization = Authorization()
authentication = SessionAuthentication()
list_allowed_methods = ['get', 'post']
class Meta:
queryset = Item.objects.filter()
def get_object_list(self, request):
return super(ItemResource, self).get_object_list(request).filter(user=request.user)
def apply_authorization_limits(self, request, object_list):
return object_list.filter(user=request.user)
def dehydrate(self, bundle):
# how to modify bundle['body'] here ? so it work
return bundle
Obviously JSONfield is sublased from django's standart TextField. So when I retrieve API i receive follow:
{
"meta": {
"limit": 20,
"next": null,
"offset": 0,
"previous": null,
"total_count": 1
},
"objects": [
{
"body": "{u'valid': u'json'}",
"id": 1,
"resource_uri": "/api/v1/testitem/1/"
}
]
}
and this is what I want to receive:
{
"meta": {
"limit": 20,
"next": null,
"offset": 0,
"previous": null,
"total_count": 1
},
"objects": [
{
"body": {
"valid': "json"
},
"id": 1,
"resource_uri": "/api/v1/testitem/1/"
}
]
}
Notice difference in body
field?
And if I do:
def dehydrate(self, bundle):
bundle['body'] = json.loads(bundle['body'])
return bundle
I receive this exception:
{"error_message": "Expecting property name: line 1 column 1 (char 1)", "traceback": "Traceback (most recent call last):\n\n File \"/Users/polinom/Envs/django/lib/python2.7/site-packages/tastypie/resources.py\", line 202, in wrapper\n response = callback(request, *args, **kwargs)\n\n File \"/Users/polinom/Envs/django/lib/python2.7/site-packages/tastypie/resources.py\", line 439, in dispatch_list\n return self.dispatch('list', request, **kwargs)\n\n File \"/Users/polinom/Envs/django/lib/python2.7/site-packages/tastypie/resources.py\", line 471, in dispatch\n response = method(request, **kwargs)\n\n File \"/Users/polinom/Envs/django/lib/python2.7/site-packages/tastypie/resources.py\", line 1270, in get_list\n bundles.append(self.full_dehydrate(bundle))\n\n File \"/Users/polinom/Envs/django/lib/python2.7/site-packages/tastypie/resources.py\", line 845, in full_dehydrate\n bundle = self.dehydrate(bundle)\n\n File \"/Users/polinom/workspace/microjob/applications/examinations/api.py\", line 24, in dehydrate\n bundle.data['body'] = json.loads(bundle.data['body'])\n\n File \"/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/__init__.py\", line 326, in loads\n return _default_decoder.decode(s)\n\n File \"/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/decoder.py\", line 360, in decode\n obj, end = self.raw_decode(s, idx=_w(s, 0).end())\n\n File \"/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/decoder.py\", line 376, in raw_decode\n obj, end = self.scan_once(s, idx)\n\nValueError: Expecting property name: line 1 column 1 (char 1)\n"}
Upvotes: 1
Views: 1118
Reputation: 3687
After creating the bundle(s), the response is created by serializing the content. For json format and default Serializer, it first convert any complex type to python basic types and then dumps it in a string representation.
As you can see, in the case of a original string, it justs convert it to unicode. You need to convert it to a dict
before serialize the resource. So, in the dehydrate
method you can do:
def dehydrate(self, bundle):
bundle['body'] = json.loads(bundle.data['body'])
return bundle
Since you are only modifying one element, you can also can do:
def dehydrate_body(self, bundle):
return json.loads(bundle.data['body'])
The JSONField stores a python dict representation, not a JSON representation. So, my first attempt is incorrect. You can return eval(bundle.data['body'])
. IMO the use of eval
here is safe because the JSONField ensures that the content is a statement that can be directly translated to a json representation.
Upvotes: 4