1# dialects/sqlite/json.py
2# Copyright (C) 2005-2026 the SQLAlchemy authors and contributors
3# <see AUTHORS file>
4#
5# This module is part of SQLAlchemy and is released under
6# the MIT License: https://www.opensource.org/licenses/mit-license.php
7from __future__ import annotations
8
9from typing import Any
10from typing import TYPE_CHECKING
11
12from ... import types as sqltypes
13from ...sql import func
14from ...sql.sqltypes import _T_JSON
15
16if TYPE_CHECKING:
17 from ...engine.interfaces import Dialect
18 from ...sql.elements import ColumnElement
19 from ...sql.type_api import _BindProcessorType
20 from ...sql.type_api import _LiteralProcessorType
21
22
23class JSON(sqltypes.JSON[_T_JSON]):
24 """SQLite JSON type.
25
26 SQLite supports JSON as of version 3.9 through its JSON1_ extension. Note
27 that JSON1_ is a
28 `loadable extension <https://www.sqlite.org/loadext.html>`_ and as such
29 may not be available, or may require run-time loading.
30
31 :class:`_sqlite.JSON` is used automatically whenever the base
32 :class:`_types.JSON` datatype is used against a SQLite backend.
33
34 .. seealso::
35
36 :class:`_types.JSON` - main documentation for the generic
37 cross-platform JSON datatype.
38
39 The :class:`_sqlite.JSON` type supports persistence of JSON values
40 as well as the core index operations provided by :class:`_types.JSON`
41 datatype, by adapting the operations to render the ``JSON_EXTRACT``
42 function wrapped in the ``JSON_QUOTE`` function at the database level.
43 Extracted values are quoted in order to ensure that the results are
44 always JSON string values.
45
46
47 .. _JSON1: https://www.sqlite.org/json1.html
48
49 """
50
51
52class JSONB(JSON[_T_JSON]):
53 """SQLite JSONB type.
54
55 Stores JSON data in SQLite's binary JSONB format, available as of
56 SQLite version 3.45.0. The binary format is more compact and faster
57 to parse than the text-based :class:`_sqlite.JSON` type.
58
59 Values are transparently stored using the ``jsonb()`` SQL function and
60 retrieved as text JSON via the ``json()`` SQL function, so the Python
61 side behaves identically to :class:`_sqlite.JSON`.
62
63 .. versionadded:: 2.1b3
64
65 .. seealso::
66
67 :class:`_sqlite.JSON`
68
69 https://sqlite.org/jsonb.html
70
71 """
72
73 __visit_name__ = "JSONB"
74
75 def bind_expression(
76 self, bindvalue: ColumnElement[Any]
77 ) -> ColumnElement[Any]:
78 return func.jsonb(bindvalue, type_=self)
79
80 def column_expression(self, col: ColumnElement[Any]) -> ColumnElement[Any]:
81 return func.json(col, type_=self)
82
83
84# Note: these objects currently match exactly those of MySQL, however since
85# these are not generalizable to all JSON implementations, remain separately
86# implemented for each dialect.
87class _FormatTypeMixin:
88 def _format_value(self, value: Any) -> str:
89 raise NotImplementedError()
90
91 def bind_processor(self, dialect: Dialect) -> _BindProcessorType[Any]:
92 super_proc = self.string_bind_processor(dialect) # type: ignore[attr-defined] # noqa: E501
93
94 def process(value: Any) -> Any:
95 value = self._format_value(value)
96 if super_proc:
97 value = super_proc(value)
98 return value
99
100 return process
101
102 def literal_processor(
103 self, dialect: Dialect
104 ) -> _LiteralProcessorType[Any]:
105 super_proc = self.string_literal_processor(dialect) # type: ignore[attr-defined] # noqa: E501
106
107 def process(value: Any) -> str:
108 value = self._format_value(value)
109 if super_proc:
110 value = super_proc(value)
111 return value # type: ignore[no-any-return]
112
113 return process
114
115
116class JSONIndexType(_FormatTypeMixin, sqltypes.JSON.JSONIndexType):
117 def _format_value(self, value: Any) -> str:
118 if isinstance(value, int):
119 formatted_value = "$[%s]" % value
120 else:
121 formatted_value = '$."%s"' % value
122 return formatted_value
123
124
125class JSONPathType(_FormatTypeMixin, sqltypes.JSON.JSONPathType):
126 def _format_value(self, value: Any) -> str:
127 return "$%s" % (
128 "".join(
129 [
130 "[%s]" % elem if isinstance(elem, int) else '."%s"' % elem
131 for elem in value
132 ]
133 )
134 )