json.py 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. # dialects/mysql/json.py
  2. # Copyright (C) 2005-2025 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
  7. from __future__ import annotations
  8. from typing import Any
  9. from typing import TYPE_CHECKING
  10. from ... import types as sqltypes
  11. if TYPE_CHECKING:
  12. from ...engine.interfaces import Dialect
  13. from ...sql.type_api import _BindProcessorType
  14. from ...sql.type_api import _LiteralProcessorType
  15. class JSON(sqltypes.JSON):
  16. """MySQL JSON type.
  17. MySQL supports JSON as of version 5.7.
  18. MariaDB supports JSON (as an alias for LONGTEXT) as of version 10.2.
  19. :class:`_mysql.JSON` is used automatically whenever the base
  20. :class:`_types.JSON` datatype is used against a MySQL or MariaDB backend.
  21. .. seealso::
  22. :class:`_types.JSON` - main documentation for the generic
  23. cross-platform JSON datatype.
  24. The :class:`.mysql.JSON` type supports persistence of JSON values
  25. as well as the core index operations provided by :class:`_types.JSON`
  26. datatype, by adapting the operations to render the ``JSON_EXTRACT``
  27. function at the database level.
  28. """
  29. pass
  30. class _FormatTypeMixin:
  31. def _format_value(self, value: Any) -> str:
  32. raise NotImplementedError()
  33. def bind_processor(self, dialect: Dialect) -> _BindProcessorType[Any]:
  34. super_proc = self.string_bind_processor(dialect) # type: ignore[attr-defined] # noqa: E501
  35. def process(value: Any) -> Any:
  36. value = self._format_value(value)
  37. if super_proc:
  38. value = super_proc(value)
  39. return value
  40. return process
  41. def literal_processor(
  42. self, dialect: Dialect
  43. ) -> _LiteralProcessorType[Any]:
  44. super_proc = self.string_literal_processor(dialect) # type: ignore[attr-defined] # noqa: E501
  45. def process(value: Any) -> str:
  46. value = self._format_value(value)
  47. if super_proc:
  48. value = super_proc(value)
  49. return value # type: ignore[no-any-return]
  50. return process
  51. class JSONIndexType(_FormatTypeMixin, sqltypes.JSON.JSONIndexType):
  52. def _format_value(self, value: Any) -> str:
  53. if isinstance(value, int):
  54. formatted_value = "$[%s]" % value
  55. else:
  56. formatted_value = '$."%s"' % value
  57. return formatted_value
  58. class JSONPathType(_FormatTypeMixin, sqltypes.JSON.JSONPathType):
  59. def _format_value(self, value: Any) -> str:
  60. return "$%s" % (
  61. "".join(
  62. [
  63. "[%s]" % elem if isinstance(elem, int) else '."%s"' % elem
  64. for elem in value
  65. ]
  66. )
  67. )