Json documentation improved

This commit is contained in:
Daniele Varrazzo 2012-09-24 11:51:35 +01:00
parent a3418052e9
commit 71e2f190c2
2 changed files with 70 additions and 61 deletions

View File

@ -134,25 +134,81 @@ Additional data types
pair: JSON; Data types pair: JSON; Data types
pair: JSON; Adaptation pair: JSON; Adaptation
JSON adaptation JSON_ adaptation
^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^
.. versionadded:: 2.4.6 .. versionadded:: 2.4.6
Psycopg can use an underlying JSON_ module implementation to adapt Python Psycopg can adapt Python objects to and from the PostgreSQL |pgjson|_ type.
objects to and from the PostgreSQL |pgjson|_ data type. The library used With PostgreSQL 9.2 adaptation is available out-of-the-box. To use JSON data
depends on the Python version: with Python 2.6 and following the with previous database versions (either with the `9.1 json extension`__, but
:py:mod:`json` module from the standard library is used; with previous even if you want to convert text fields to JSON) you can use
versions the `simplejson`_ module is be used if available. Note that the last `register_json()`.
`!simplejson` version supporting Python 2.4 is the 2.0.9.
.. __: http://people.planetpostgresql.org/andrew/index.php?/archives/255-JSON-for-PG-9.2-...-and-now-for-9.1!.html
The Python library used to convert Python objects to JSON depends on the
language version: with Python 2.6 and following the :py:mod:`json` module from
the standard library is used; with previous versions the `simplejson`_ module
is used if available. Note that the last `!simplejson` version supporting
Python 2.4 is the 2.0.9.
.. _JSON: http://www.json.org/ .. _JSON: http://www.json.org/
.. |pgjson| replace:: :sql:`json` .. |pgjson| replace:: :sql:`json`
.. _pgjson: http://www.postgresql.org/docs/current/static/datatype-json.html .. _pgjson: http://www.postgresql.org/docs/current/static/datatype-json.html
.. _simplejson: http://pypi.python.org/pypi/simplejson/ .. _simplejson: http://pypi.python.org/pypi/simplejson/
In order to pass a Python object to the database as query argument you can use
the `Json` adapter::
curs.execute("insert into mytable (jsondata) values (%s)",
[Json({'a': 100})])
Reading from the database, |pgjson| values will be automatically converted to
Python objects.
.. note::
You can use `~psycopg2.extensions.register_adapter()` to adapt any Python
dictionary to JSON, either registering `Json` or any subclass or factory
creating a compatible adapter::
psycopg2.extensions.register_adapter(dict, psycopg2.extras.Json)
This setting is global though, so it is not compatible with similar
adapters such as the one registered by `register_hstore()`. Any other
object supported by JSON can be registered the same way, but this will
clobber the default adaptation rule, so be careful to unwanted side
effects.
If you want to customize the adaptation from Python to PostgreSQL you can
either provide a custom `!dumps()` function to `!Json`::
curs.execute("insert into mytable (jsondata) values (%s)",
[Json({'a': 100}, dumps=simplejson.dumps)])
or you can subclass it overriding the `~Json.dumps()` method::
class MyJson(Json):
def dumps(self, obj):
return simplejson.dumps(obj)
curs.execute("insert into mytable (jsondata) values (%s)",
[MyJson({'a': 100})])
Customizing the conversion from PostgreSQL to Python can be done passing a
custom `!loads()` function to `register_json()` (or `register_default_json()`
for PostgreSQL 9.2). For example, if you want to convert the float values
from :sql:`json` into :py:class:`~decimal.Decimal` you can use::
loads = lambda x: json.loads(x, parse_float=Decimal)
psycopg2.extras.register_json(conn, loads=loads)
.. autoclass:: Json .. autoclass:: Json
:members: dumps
.. automethod:: dumps
.. autofunction:: register_json .. autofunction:: register_json

View File

@ -52,43 +52,11 @@ class Json(object):
An `~psycopg2.extensions.ISQLQuote` wrapper to adapt a Python object to An `~psycopg2.extensions.ISQLQuote` wrapper to adapt a Python object to
:sql:`json` data type. :sql:`json` data type.
`!Json` can be used to wrap any object supported by the underlying `!Json` can be used to wrap any object supported by the provided *dumps*
`!json` module. `~psycopg2.extensions.ISQLQuote.getquoted()` will raise function. If none is provided, the standard :py:func:`json.dumps()` is
`!ImportError` if no module is available. used (`!simplejson` for Python < 2.6;
`~psycopg2.extensions.ISQLQuote.getquoted()` will raise `!ImportError` if
The basic usage is to wrap `!Json` around the object to be adapted:: the module is available).
curs.execute("insert into mytable (jsondata) values (%s)",
[Json({'a': 100})])
If you want to customize the adaptation from Python to PostgreSQL you can
either provide a custom *dumps* function::
curs.execute("insert into mytable (jsondata) values (%s)",
[Json({'a': 100}, dumps=simplejson.dumps)])
or you can subclass `!Json` overriding the `dumps()` method::
class MyJson(Json):
def dumps(self, obj):
return simplejson.dumps(obj)
curs.execute("insert into mytable (jsondata) values (%s)",
[MyJson({'a': 100})])
.. note::
You can use `~psycopg2.extensions.register_adapter()` to adapt any
Python dictionary to JSON, either using `!Json` or any subclass or
factory creating a compatible adapter::
psycopg2.extensions.register_adapter(dict, psycopg2.extras.Json)
This setting is global though, so it is not compatible with similar
adapters such as the one registered by `register_hstore()`. Any other
object supported by JSON can be registered the same way, but this will
clobber the default adaptation rule, so be careful to unwanted side
effects.
""" """
def __init__(self, adapted, dumps=None): def __init__(self, adapted, dumps=None):
@ -143,20 +111,6 @@ def register_json(conn_or_curs=None, globally=False, loads=None,
:param array_oid: the OID of the :sql:`json[]` array type if known; :param array_oid: the OID of the :sql:`json[]` array type if known;
if not, it will be queried on *conn_or_curs* if not, it will be queried on *conn_or_curs*
Using the function is required to convert :sql:`json` data in PostgreSQL
versions before 9.2. Since 9.2 the oids are hardcoded so a default
typecaster is already registered. The :sql:`json` type is available as
`extension for PostgreSQL 9.1`__.
.. __: http://people.planetpostgresql.org/andrew/index.php?/archives/255-JSON-for-PG-9.2-...-and-now-for-9.1!.html
Another use of the function is to adapt :sql:`json` using a customized
load function. For example, if you want to convert the float values in the
:sql:`json` into :py:class:`~decimal.Decimal` you can use::
loads = lambda x: json.loads(x, parse_float=Decimal)
psycopg2.extras.register_json(conn, loads=loads)
The connection or cursor passed to the function will be used to query the The connection or cursor passed to the function will be used to query the
database and look for the OID of the :sql:`json` type. No query is database and look for the OID of the :sql:`json` type. No query is
performed if *oid* and *array_oid* are provided. Raise performed if *oid* and *array_oid* are provided. Raise
@ -187,7 +141,6 @@ def register_default_json(conn_or_curs=None, globally=False, loads=None):
return register_json(conn_or_curs=conn_or_curs, globally=globally, return register_json(conn_or_curs=conn_or_curs, globally=globally,
loads=loads, oid=JSON_OID, array_oid=JSONARRAY_OID) loads=loads, oid=JSON_OID, array_oid=JSONARRAY_OID)
def _create_json_typecasters(oid, array_oid, loads=None): def _create_json_typecasters(oid, array_oid, loads=None):
"""Create typecasters for json data type.""" """Create typecasters for json data type."""
if loads is None: if loads is None: