Source code for sqlalchemy_utils.types.json

from __future__ import absolute_import

import six
import sqlalchemy as sa
from sqlalchemy.dialects.postgresql.base import ischema_names

from ..exceptions import ImproperlyConfigured

json = None
try:
    import anyjson as json
except ImportError:
    import json as json

try:
    from sqlalchemy.dialects.postgresql import JSON
    has_postgres_json = True
except ImportError:
    class PostgresJSONType(sa.types.UserDefinedType):
        """
        Text search vector type for postgresql.
        """
        def get_col_spec(self):
            return 'json'

    ischema_names['json'] = PostgresJSONType
    has_postgres_json = False


[docs]class JSONType(sa.types.TypeDecorator): """ JSONType offers way of saving JSON data structures to database. On PostgreSQL the underlying implementation of this data type is 'json' while on other databases its simply 'text'. :: from sqlalchemy_utils import JSONType class Product(Base): __tablename__ = 'product' id = sa.Column(sa.Integer, autoincrement=True) name = sa.Column(sa.Unicode(50)) details = sa.Column(JSONType) product = Product() product.details = { 'color': 'red', 'type': 'car', 'max-speed': '400 mph' } session.commit() """ impl = sa.UnicodeText def __init__(self, *args, **kwargs): if json is None: raise ImproperlyConfigured( 'JSONType needs anyjson package installed.' ) super(JSONType, self).__init__(*args, **kwargs) def load_dialect_impl(self, dialect): if dialect.name == 'postgresql': # Use the native JSON type. if has_postgres_json: return dialect.type_descriptor(JSON()) else: return dialect.type_descriptor(PostgresJSONType()) else: return dialect.type_descriptor(self.impl) def process_bind_param(self, value, dialect): if dialect.name == 'postgresql' and has_postgres_json: return value if value is not None: value = six.text_type(json.dumps(value)) return value def process_result_value(self, value, dialect): if dialect.name == 'postgresql': return value if value is not None: value = json.loads(value) return value