Added JSONType
This commit is contained in:
3
setup.py
3
setup.py
@@ -35,6 +35,7 @@ extras_require = {
|
||||
'flexmock>=0.9.7',
|
||||
'psycopg2>=2.4.6',
|
||||
],
|
||||
'anyjson': ['anyjson>=0.3.3'],
|
||||
'babel': ['Babel>=1.3'],
|
||||
'arrow': ['arrow>=0.3.4'],
|
||||
'phone': [
|
||||
@@ -57,7 +58,7 @@ for name, requirements in extras_require.items():
|
||||
|
||||
setup(
|
||||
name='SQLAlchemy-Utils',
|
||||
version='0.19.0',
|
||||
version='0.20.0',
|
||||
url='https://github.com/kvesteri/sqlalchemy-utils',
|
||||
license='BSD',
|
||||
author='Konsta Vesterinen, Ryan Leckey, Janne Vanhala, Vesa Uimonen',
|
||||
|
51
sqlalchemy_utils/types/json.py
Normal file
51
sqlalchemy_utils/types/json.py
Normal file
@@ -0,0 +1,51 @@
|
||||
import sqlalchemy as sa
|
||||
|
||||
json = None
|
||||
try:
|
||||
import anyjson as json
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
import six
|
||||
from sqlalchemy.dialects.postgresql.base import ischema_names
|
||||
from ..exceptions import ImproperlyConfigured
|
||||
|
||||
|
||||
class PostgresJSONType(sa.types.UserDefinedType):
|
||||
"""
|
||||
Text search vector type for postgresql.
|
||||
"""
|
||||
def get_col_spec(self):
|
||||
return 'json'
|
||||
|
||||
|
||||
ischema_names['json'] = PostgresJSONType
|
||||
|
||||
|
||||
class JSONType(sa.types.TypeDecorator):
|
||||
"Represents an immutable structure as a json-encoded string."
|
||||
|
||||
impl = sa.UnicodeText
|
||||
|
||||
def __init__(self):
|
||||
if json is None:
|
||||
raise ImproperlyConfigured(
|
||||
'JSONType needs anyjson package installed.'
|
||||
)
|
||||
|
||||
def load_dialect_impl(self, dialect):
|
||||
if dialect.name == 'postgresql':
|
||||
# Use the native JSON type.
|
||||
return dialect.type_descriptor(PostgresJSONType())
|
||||
else:
|
||||
return dialect.type_descriptor(self.impl)
|
||||
|
||||
def process_bind_param(self, value, dialect):
|
||||
if value is not None:
|
||||
value = six.text_type(json.dumps(value))
|
||||
return value
|
||||
|
||||
def process_result_value(self, value, dialect):
|
||||
if value is not None:
|
||||
value = json.loads(value)
|
||||
return value
|
38
tests/types/test_json.py
Normal file
38
tests/types/test_json.py
Normal file
@@ -0,0 +1,38 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from pytest import mark
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy_utils.types import json
|
||||
from tests import TestCase
|
||||
|
||||
|
||||
@mark.skipif('json.json is None')
|
||||
class TestJSONType(TestCase):
|
||||
def create_models(self):
|
||||
class Document(self.Base):
|
||||
__tablename__ = 'document'
|
||||
id = sa.Column(sa.Integer, primary_key=True)
|
||||
json = sa.Column(json.JSONType)
|
||||
|
||||
self.Document = Document
|
||||
|
||||
def test_parameter_processing(self):
|
||||
document = self.Document(
|
||||
json={'something': 12}
|
||||
)
|
||||
|
||||
self.session.add(document)
|
||||
self.session.commit()
|
||||
|
||||
document = self.session.query(self.Document).first()
|
||||
assert document.json == {'something': 12}
|
||||
|
||||
def test_non_ascii_chars(self):
|
||||
document = self.Document(
|
||||
json={'something': u'äääööö'}
|
||||
)
|
||||
|
||||
self.session.add(document)
|
||||
self.session.commit()
|
||||
|
||||
document = self.session.query(self.Document).first()
|
||||
assert document.json == {'something': u'äääööö'}
|
Reference in New Issue
Block a user