Re: JSON type caster

Поиск
Список
Период
Сортировка
От Daniele Varrazzo
Тема Re: JSON type caster
Дата
Msg-id CA+mi_8Yv2SVOdhAtx-4CbpzoDtaJGkf8QvnushdF8bMgySAbYg@mail.gmail.com
обсуждение исходный текст
Ответ на Re: JSON type caster  (Tobias Oberstein <tobias.oberstein@gmail.com>)
Ответы Re: JSON type caster  (Tobias Oberstein <tobias.oberstein@gmail.com>)
Список psycopg
On Wed, Sep 19, 2012 at 1:36 PM, Tobias Oberstein
<tobias.oberstein@gmail.com> wrote:

> A minor inconvenience: when on PG 9.2 OIDs are well know, but when
> I need to register a custom JSON typecaster, I nevertheless need
> to supply the OIDs _or_ provide a connection (which I may want
> to avoid when I want the behavior globally):
>
> loads = lambda x: json.loads(x, parse_float = Decimal)
> psycopg2.extras.register_json(None, globally = True, loads = loads, oid =
> 114, array_oid = 199)
> #psycopg2.extras.register_json(None, globally = True, loads = loads) # won't
> work
>
> I am fine with that, but the example in the docs would probably profit
> from mentioning this code snippet .. "how to install custom JSON typecaster
> on PG92 globally".

Oh, yes, I see the use case. You are right, it's too tricky for its
usefulness. The easiest (for us) solution would be to provide symbolic
constants in psycopg2.extensions. It results in a still too verbose:

    psycopg2.extras.register_json(None, globally=True, loads=loads,
oid=ext.JSON_OID, array_oid=ext.JSONARRAY_OID)

btw there's too use for the conn_or_curs=None: I think I'll set it as
default so that it can be dropped if only kwargs are provided. The
above would become:

    psycopg2.extras.register_json(globally=True, loads=loads,
oid=ext.JSON_OID, array_oid=ext.JSONARRAY_OID)

Uhm... but what about a new function? To be called

    psycopg2.extras.register_default_json(globally=True, loads=loads)

or
    conn = psycopg2.connect(...)
    psycopg2.extras.register_default_json(conn, loads=loads)

To be implemented like:

    def register_default_json(conn_or_curs=None, globally=False, loads=None):
        """Register json adapter for PG92 and following"""
        return register_json(conn_or_curs=conn_or_curs,
globally=globally, loads=loads,
            oid=114, array_oid=199)


> Another thing that's probably inconvenient: psycopg2.extras.Json
> forwards kwargs for customization, but there is no trivial way
> of using a different "json" implementation altogether

What I didn't like reviewing the two sides is the asymmetry: adapter
taking **kwargs and typecaster taking loads function. I'm thinking
about passing a dumps function instead of the **kwargs. It could be:

    class Json(object):
        def __init__(self, adapted, dumps=None):
            self.adapted = adapted
            self._dumps = dumps is None and json.dumps or dumps

        def dumps(self):
            return self._dumps(self.adapted)

        def getquoted(self):
            s = self.dumps()
            return QuotedString(s).getquoted()

This way customization can be performed either functional-style via a closure:

    def CustomJson(adapted):
        return Json(adapted,
            dumps=lambda x: simplejson.dumps(x, parse_float=Decimal))

or oo-style via subclassing:

    class CustomJson(Json):
        def dumps(self)
            return simplejson.dumps(self.adapted, parse_float=Decimal)

Thank you for the review. Comments?

-- Daniele


В списке psycopg по дате отправления:

Предыдущее
От: Tobias Oberstein
Дата:
Сообщение: Re: JSON type caster
Следующее
От: Tobias Oberstein
Дата:
Сообщение: Re: JSON type caster