From: Daniele Varrazzo Date: Tue, 27 Oct 2020 16:09:08 +0000 (+0100) Subject: Added json text dump X-Git-Tag: 3.0.dev0~442^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=06b1b9d5b80ad038aedcc6a08d8fa54371cf060b;p=thirdparty%2Fpsycopg.git Added json text dump --- diff --git a/psycopg3/psycopg3/types/__init__.py b/psycopg3/psycopg3/types/__init__.py index f578c651c..e0ce65c36 100644 --- a/psycopg3/psycopg3/types/__init__.py +++ b/psycopg3/psycopg3/types/__init__.py @@ -8,7 +8,7 @@ psycopg3 types package from .oids import builtins # Register default adapters -from . import array, composite, numeric, text # noqa +from . import array, json, composite, numeric, text # noqa # Register associations with array oids array.register_all_arrays() diff --git a/psycopg3/psycopg3/types/json.py b/psycopg3/psycopg3/types/json.py new file mode 100644 index 000000000..0460aca9e --- /dev/null +++ b/psycopg3/psycopg3/types/json.py @@ -0,0 +1,60 @@ +""" +Adapers for JSON types. +""" + +# Copyright (C) 2020 The Psycopg Team + +import json +import codecs +from typing import Any, Callable, Optional + +from .oids import builtins +from ..adapt import Dumper +from ..proto import EncodeFunc + +_encode_utf8 = codecs.lookup("utf8").encode + +JSON_OID = builtins["json"].oid +JSONB_OID = builtins["jsonb"].oid + +JsonDumpsFunction = Callable[[Any], str] + + +class _JsonWrapper: + def __init__(self, obj: Any, dumps: Optional[JsonDumpsFunction] = None): + self.obj = obj + self._dumps: JsonDumpsFunction = dumps or json.dumps + + def dumps(self) -> str: + return self._dumps(self.obj) + + +class Json(_JsonWrapper): + pass + + +class JsonB(_JsonWrapper): + pass + + +class _JsonDumper(Dumper): + _oid: int + + def dump( + self, obj: _JsonWrapper, __encode: EncodeFunc = _encode_utf8 + ) -> bytes: + return __encode(obj.dumps())[0] + + @property + def oid(self) -> int: + return self._oid + + +@Dumper.text(Json) +class JsonDumper(_JsonDumper): + _oid = JSON_OID + + +@Dumper.text(JsonB) +class JsonBDumper(_JsonDumper): + _oid = JSONB_OID diff --git a/tests/types/test_json.py b/tests/types/test_json.py new file mode 100644 index 000000000..9fca64c34 --- /dev/null +++ b/tests/types/test_json.py @@ -0,0 +1,34 @@ +import json + +import pytest + +from psycopg3.types.json import Json, JsonB + +samples = [ + "null", + "true", + '"te\'xt"', + '"\\u00e0\\u20ac"', + "123", + "123.45", + '["a", 100]', + '{"a": 100}', +] + + +@pytest.mark.parametrize("val", samples) +def test_json_dump(conn, val): + obj = json.loads(val) + cur = conn.cursor() + cur.execute("select pg_typeof(%s) = 'json'::regtype", (Json(obj),)) + assert cur.fetchone()[0] is True + cur.execute("select %s::text = %s::json::text", (Json(obj), val)) + assert cur.fetchone()[0] is True + + +@pytest.mark.parametrize("val", samples) +def test_jsonb_dump(conn, val): + obj = json.loads(val) + cur = conn.cursor() + cur.execute("select %s = %s::jsonb", (JsonB(obj), val)) + assert cur.fetchone()[0] is True