How to make an object JSON-serializable?

105 views
Skip to first unread message

Cosmia Luna

unread,
Mar 1, 2012, 12:22:28 AM3/1/12
to pylons-...@googlegroups.com
I want to to return some SQLAlchemy object to the json renderer, of course it didn't work.
Can I add a method to the Base like:

class Base(object):
    def __jsonSerialize__(self):
        pass # return a dict-like object

Base=declarative_base(cls=Base)

Or I have to write a renderer called ejson(extendable json renderer) or some other wrapping the default json renderer?

Thanks,
Cosmia

Julien Cigar

unread,
Mar 1, 2012, 9:42:37 AM3/1/12
to pylons-...@googlegroups.com
I wrote a basic json/xml serializer some time ago:
http://www.pastie.org/3496853
It's pretty basic and unfinished at all but .. if it can help

> --
> You received this message because you are subscribed to the Google
> Groups "pylons-discuss" group.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/pylons-discuss/-/GW86sjghplgJ.
> To post to this group, send email to pylons-...@googlegroups.com.
> To unsubscribe from this group, send email to
> pylons-discus...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/pylons-discuss?hl=en.


--
No trees were killed in the creation of this message.
However, many electrons were terribly inconvenienced.

jcigar.vcf

Robert Forkel

unread,
Mar 1, 2012, 9:50:18 AM3/1/12
to pylons-...@googlegroups.com

I use a combination of this. A __json__ method on Base, and a custom json renderer, taking this method into account.
Regards
Robert

--

Alexis Métaireau

unread,
Mar 1, 2012, 10:04:50 AM3/1/12
to pylons-...@googlegroups.com, Robert Forkel
What I'm doing is to add a property on the models I want to serialize,
and to use a custom json serializer for this purpose.

Have a look at
https://github.com/spiral-project/ihatemoney/blob/master/budget/models.py#L12
and
https://github.com/ametaireau/flask-rest/blob/master/flask_rest.py#L144

However, this isn't automatic, and it is probably possible to automate
this without having to explicitly specify what you want to serialize
(like Julien did)

Cosmia Luna

unread,
Mar 1, 2012, 10:13:05 AM3/1/12
to pylons-...@googlegroups.com
Hmm... It seems that renderer doesn't have such a interface, but that's OK, because writing a renderer is so easy.

Thanks,
Cosmia

Cosmia Luna

unread,
Mar 1, 2012, 10:24:54 AM3/1/12
to pylons-...@googlegroups.com, Robert Forkel
May be you can try to look into the just add such a line to the base, it can help you get the list of defined properties of the model,

class Base(object):
    def __init__(self, *args, **kwargs):
        # do your business here
        self.
_to_serialize=self.__table__.columns.keys()
        # do some other thing or add other stuff you want to serialize

But it can only return those explicitly defined columns, properties won't be returned, you can add them later.

Regards,
Cosmia

Cosmia Luna

unread,
Mar 1, 2012, 10:30:48 AM3/1/12
to pylons-...@googlegroups.com, Robert Forkel
PS: I meant "you can try to look into the Base.__table__.columns object

Regards,
Cosmia

John Anderson

unread,
Mar 1, 2012, 12:13:51 PM3/1/12
to pylons-...@googlegroups.com, Robert Forkel
This is the code I use (if your e-mail doesn't preview code well: http://paste2.org/p/1921598):

    def serialize(self, localtz=None):
        """Converts all the properties of the object into a dict
        for use in json
        """
        props = {}

        def is_valid_key(key):
            if not key.startswith('_') and \
               not 'password' in key and \
               not 'salt' == key:
               return True

        _items = self.__class__.__dict__
        local_at = dict()
        if _items.has_key('timezone') and (getattr(self, 'timezone') or localtz):
            timezone = localtz or getattr(self,'timezone')
            if _items.has_key('start_time') and getattr(self,'start_time'):
                local_at.update(self._localize_time('start_date', 'start_time', timezone.name))
            if _items.has_key('end_time') and getattr(self,'end_time'):
                local_at.update(self._localize_time('end_date', 'end_time', timezone.name))

        for key, value in _items.items():
            if is_valid_key(key):
                obj = getattr(self, key)
                if hasattr(obj, 'serialize'):
                    props[key] = obj.serialize()
                elif not callable(obj):
                    if isinstance(obj, datetime) or isinstance(obj, date):
                        _date = local_at.get(key,None) or obj
                        props[key] = _date.strftime("%Y-%m-%d")
                    elif isinstance(obj, time):
                        _time = local_at.get(key,None) or obj
                        props[key] = _time.strftime("%I:%M %p")
                    else:
                        props[key] = getattr(self, key)

        props['id'] = str(self.pk)

        return props



--
You received this message because you are subscribed to the Google Groups "pylons-discuss" group.
To view this discussion on the web visit https://groups.google.com/d/msg/pylons-discuss/-/TOFfc3SAPXEJ.

Andrey Popp

unread,
Mar 1, 2012, 2:36:22 PM3/1/12
to Cosmia Luna, pylons-...@googlegroups.com

Sorry for self-advertisement, but I've wrote a small utility to solve this kind
of problems -- jsonpublish[1]. Code looks like this:

class Base(object):
pass

from jsonpublish import register_adapter, dumps

@register_adapter(Base)
def adapt_base(b):
return {} # adapt Base object to json-encodable structure

dumps(Base()) # now it works!

See docs[1] for more info.

[1]: http://jsonpublish.readthedocs.org/en/latest/index.html

Reply all
Reply to author
Forward
0 new messages