json serialization without certain fields and with extra information?

2,779 views
Skip to first unread message

Bram - Smartelectronix

unread,
Feb 28, 2007, 7:44:36 AM2/28/07
to django...@googlegroups.com
hey everyone,


1. is there any way to serialize models and remove some fields? I.e. I
would like to serialize User for example, but I definitely don't want
the email to be there.

2. is there a way to provide "custom" parts of the serialization? For
example, when serializing a Book I would like to see it's "tags" even if
they are just an array of tags without tag-id etc etc

In general I would like to create some API pages that dump JSON. It
would be great to be able to specify which parts of an object are
"private" and which are "public" and which are "additional" so I could
automatically do this.

Any hints appreciated!


- bram

limodou

unread,
Feb 28, 2007, 8:10:51 AM2/28/07
to django...@googlegroups.com
you can just create your own dict variable, and then using simplejson
to convert it to json


--
I like python!
UliPad <<The Python Editor>>: http://wiki.woodpecker.org.cn/moin/UliPad
My Blog: http://www.donews.net/limodou

Bram - Smartelectronix

unread,
Feb 28, 2007, 9:25:01 AM2/28/07
to django...@googlegroups.com
limodou wrote:
> On 2/28/07, Bram - Smartelectronix <br...@smartelectronix.com> wrote:
>> hey everyone,
>>
>>
>> 1. is there any way to serialize models and remove some fields? I.e. I
>> would like to serialize User for example, but I definitely don't want
>> the email to be there.
>>
>> 2. is there a way to provide "custom" parts of the serialization? For
>> example, when serializing a Book I would like to see it's "tags" even if
>> they are just an array of tags without tag-id etc etc
>>
>> In general I would like to create some API pages that dump JSON. It
>> would be great to be able to specify which parts of an object are
>> "private" and which are "public" and which are "additional" so I could
>> automatically do this.
>>
>> Any hints appreciated!
>>
> you can just create your own dict variable, and then using simplejson
> to convert it to json

Of course, but that's exactly what I'm trying to avoid...

- bram

limodou

unread,
Feb 28, 2007, 9:29:12 AM2/28/07
to django...@googlegroups.com
django also uses simplejson to dump python variable, why you want to
avoid it? And I think using simplejson is more flexiable and simple.

Bram - Smartelectronix

unread,
Feb 28, 2007, 10:41:49 AM2/28/07
to django...@googlegroups.com
limodou wrote:
> django also uses simplejson to dump python variable, why you want to
> avoid it? And I think using simplejson is more flexiable and simple.

Because it's more generic and I don't want to recreate what's done in
the models...

In the end I did it like this:

# MODEL --------------------------------------------

class Book():
hidden_field = ...
user = foreign key

def api_additional(self)
return ({"username": user.username}, ["hidden_field"])

# VIEW --------------------------------------------

def api(request, id, model):
serializer = CustomJSONSerializer()
value = serializer.serialize(model.objects.filter(id=id))
return HttpResponse(value, mimetype='application/javascript')

# CustomJSONSerializer --------------------------------------------

class CustomJSONSerializer(JSONSerializer):
def end_object(self, obj):
super(JSONSerializer, self).end_object(obj)

fields = self.objects[-1]["fields"]
try:
additional_fields, removed_fields = obj.api_additional()

# remove the unwanted fields
for field in removed_fields:
if field in fields.keys():
del fields[field]

# add the additional fields
fields.update(additional_fields)
except AttributeError:
pass

# URLS --------------------------------------------

urlpatterns = patterns('bookshop.api.views',
(r'^models/book/(?P<id>\d+)/$', 'api', {"model": Book}),


Thus getting almost-for-free serialization with hidden fiends and
additional data :-) Perhaps something like this (but a bit smarter)
should go into the Serialization?


- bram

limodou

unread,
Feb 28, 2007, 8:18:58 PM2/28/07
to django...@googlegroups.com
My code will seem like:

def _get_data(request, obj):
if obj.icon:
icon = '<img class="border" src="/site_media/%s" alt="%s"/>' %
(obj.get_icon_url(), obj.title)
else:
icon = '<img class="border"
src="/site_media/img/book_icon.jpg" alt="%s"/>' % obj.title
authors = [x.username for x in obj.authors.all()]
return ({'id':obj.id, 'icon':icon, 'title':obj.title,
'description':obj.description, 'author':','.join(authors),
'modifydate':obj.modifydate.strftime("%b %d,%Y %I:%m %p")})

def ajax_list(request):
result = []
objs = Book.objects.all()
for o in objs:
result.append(_get_data(request, o))
return json_response(result)

So I'd like write my own data gather method, and it can return other
data just like html snippets except for field value.

And for json method should be:

def json_response(data):
encode = settings.DEFAULT_CHARSET
return HttpResponse(simplejson.dumps(uni_str(data, encode)))

def uni_str(a, encoding=None):
if not encoding:
encoding = settings.DEFAULT_CHARSET
if isinstance(a, (list, tuple)):
s = []
for i, k in enumerate(a):
s.append(uni_str(k, encoding))
return s
elif isinstance(a, dict):
s = {}
for i, k in enumerate(a.items()):
key, value = k
s[uni_str(key, encoding)] = uni_str(value, encoding)
return s
elif isinstance(a, unicode):
return a
elif isinstance(a, (int, float)):
return a
elif isinstance(a, str) or (hasattr(a, '__str__') and
callable(getattr(a, '__str__'))):
if getattr(a, '__str__'):
a = str(a)
return unicode(a, encoding)
else:
return a

You can put json_response and uni_str into a module file. So I think
the work will be not so hard.

Deryck Hodge

unread,
Feb 28, 2007, 8:46:51 PM2/28/07
to django...@googlegroups.com
On 2/28/07, Bram - Smartelectronix <br...@smartelectronix.com> wrote:
>
> hey everyone,
>
>
> 1. is there any way to serialize models and remove some fields? I.e. I
> would like to serialize User for example, but I definitely don't want
> the email to be there.
>

The serializer in trunk has a fields option, which only serializes the
fields supplied.

Ex:
serializers.serialize('json', my_user_set, fields=('username', 'id'))

Cheers,
deryck

Manoj Govindan

unread,
Mar 1, 2007, 2:37:15 AM3/1/07
to Django users

> The serializer in trunk has a fields option, which only serializes the
> fields supplied.
>
> Ex:
> serializers.serialize('json', my_user_set, fields=('username', 'id'))

This doesn't work at the moment
http://code.djangoproject.com/ticket/3466

But luckily there is also a patch ;)

Regards,
Manoj

Bram - Smartelectronix

unread,
Mar 1, 2007, 5:23:50 AM3/1/07
to django...@googlegroups.com

Also, this isn't enough...

It would be better/cooler to be able to give "extra" fields and "fields
you DON'T want". The extra could be a callback used on each item in the
sequence:

# note, this is a pretty dumb example :-)
def generate_extra_user_data(user):
return {
"user_tags": [tag.name for tag in user.tag_set.all()],
"username_uppercase": user.username.upper(),
}

serializers.serialize('json',
my_user_set,
extra=generate_extra_user_data,
hidden=["password", "email"])

Now one could go even one step further and add the
generate_extra_user_data and 'hidden' to -for example- the Meta of your
models and call it automatically from the serializer.


- bram

Manoj Govindan

unread,
Mar 5, 2007, 2:09:11 AM3/5/07
to Django users
Hi Bram,
Here is a possible mechanism to address your second point, i.e., hide
certain fields while serializing.

Consider this model:
class Person(models.Model):
... # various fields here.

@staticmethod
def fields_for_serializing():
return [list of those field names that can be serialized]

You can then invoke this method while serializing.

serializers.serialize('json', Person.objects.all(), fields =
Person.fields_for_serializing())

Regards,
Manoj

shevken

unread,
Mar 10, 2007, 8:00:47 AM3/10/07
to Django users
Hey guys,

How do you de-serialize the object back at the ajax response.

class Cart(models.Model):
...
def get_total_quantity():
return quantity;

self.response = self.xmlhttp.responseText;

// parse the response into a JSON object
var json_data = self.response.parseJSON();

alert(json_data.get_total_quantity())

ERROR:
[Exception... "'SyntaxError: parseJSON' when calling method:
[nsIOnReadyStateChangeHandler::handleEvent]" nsresult: "0x8057001c
(NS_ERROR_XPC_JS_THREW_JS_OBJECT)" location: "<unknown>" data: no]

Line 0

Best Wishes,
Kenny

Reply all
Reply to author
Forward
0 new messages