Added register_default_json() function

Register a typecaster for PostgreSQL 9.2 json.
This commit is contained in:
Daniele Varrazzo 2012-09-19 15:49:00 +01:00
parent 26d71b4cba
commit d963b478e2
5 changed files with 43 additions and 9 deletions

View File

@ -155,6 +155,8 @@ versions the `simplejson`_ module is be used if available. Note that the last
.. autofunction:: register_json
.. autofunction:: register_default_json
.. _adapt-hstore:

View File

@ -43,6 +43,10 @@ else:
json = None
# oids from PostgreSQL 9.2
JSON_OID = 114
JSONARRAY_OID = 199
class Json(object):
"""A wrapper to adapt a Python object to :sql:`json` data type.
@ -130,7 +134,7 @@ def register_json(conn_or_curs=None, globally=False, loads=None,
if oid is None:
oid, array_oid = _get_json_oids(conn_or_curs)
JSON, JSONARRAY = create_json_typecasters(oid, array_oid, loads)
JSON, JSONARRAY = _create_json_typecasters(oid, array_oid, loads)
register_type(JSON, not globally and conn_or_curs or None)
@ -139,7 +143,20 @@ def register_json(conn_or_curs=None, globally=False, loads=None,
return JSON, JSONARRAY
def create_json_typecasters(oid, array_oid, loads=None):
def register_default_json(conn_or_curs=None, globally=False, loads=None):
"""
Create and register :sql:`json` typecasters for PostgreSQL 9.2 and following.
Since PostgreSQL 9.2 :sql:`json` is a builtin type, hence its oid is known
and fixed. This function allows specifying a customized *loads* function
for the default :sql:`json` type without querying the database.
All the parameters have the same meaning of `register_json()`.
"""
return register_json(conn_or_curs=conn_or_curs, globally=globally,
loads=loads, oid=JSON_OID, array_oid=JSONARRAY_OID)
def _create_json_typecasters(oid, array_oid, loads=None):
"""Create typecasters for json data type."""
if loads is None:
if json is None:

View File

@ -151,17 +151,14 @@ class NoneAdapter(object):
# Create default json typecasters for PostgreSQL 9.2 oids
from psycopg2._json import create_json_typecasters
from psycopg2._json import register_default_json
try:
JSON, JSONARRAY = create_json_typecasters(114, 199)
JSON, JSONARRAY = register_default_json()
except ImportError:
pass
else:
register_type(JSON)
register_type(JSONARRAY)
del create_json_typecasters
del register_default_json
# Add the "cleaned" version of the encodings to the key.

View File

@ -970,7 +970,7 @@ def register_composite(name, conn_or_curs, globally=False):
# expose the json adaptation stuff into the module
from psycopg2._json import json, Json, register_json
from psycopg2._json import json, Json, register_json, register_default_json
__all__ = filter(lambda k: not k.startswith('_'), locals().keys())

View File

@ -950,6 +950,24 @@ class JsonTestCase(unittest.TestCase):
if olda:
psycopg2.extensions.register_type(olda)
@skip_if_no_json_module
@skip_before_postgres(9, 2)
def test_register_default(self):
curs = self.conn.cursor()
loads = lambda x: psycopg2.extras.json.loads(x, parse_float=Decimal)
psycopg2.extras.register_default_json(curs, loads=loads)
curs.execute("""select '{"a": 100.0, "b": null}'::json""")
data = curs.fetchone()[0]
self.assert_(isinstance(data['a'], Decimal))
self.assertEqual(data['a'], Decimal('100.0'))
curs.execute("""select array['{"a": 100.0, "b": null}']::json[]""")
data = curs.fetchone()[0]
self.assert_(isinstance(data[0]['a'], Decimal))
self.assertEqual(data[0]['a'], Decimal('100.0'))
def test_suite():
return unittest.TestLoader().loadTestsFromName(__name__)