Auto-decode columns declared as JSON in output modes (issue #579)

Columns declared with type JSON now decode automatically wherever nested
JSON is already supported (query/rows/search/memory output, and the
Python API), without needing --json-cols. Uses sqlite3's built-in
detect_types=PARSE_DECLTYPES + a registered JSON converter, so it works
transparently through joins and aliases. Flat formats (CSV/TSV/table/raw)
re-serialize decoded values back to JSON text instead of a Python repr.
Also adds "JSON" as a first-class column type for create()/add_column()/
transform(), and fixes column_affinity("JSON") so transform() doesn't
rewrite JSON columns as REAL.
This commit is contained in:
Parker Gurney 2026-08-05 14:18:25 -07:00
commit f34dfb25da
8 changed files with 99 additions and 10 deletions

View file

@ -192,7 +192,15 @@ If one of your columns contains JSON, by default it will be returned as an escap
}
]
You can use the ``--json-cols`` option to automatically detect these JSON columns and output them as nested JSON data:
If the column is declared as type ``JSON`` in the table's schema, this happens automatically without needing ``--json-cols``:
.. code-block:: bash
sqlite-utils dogs.db "CREATE TABLE dogs2 (id integer primary key, name text, friends JSON)"
Columns declared this way are decoded as nested JSON by every command that returns JSON (``rows``, ``query``, ``search``, ``memory``), and by the Python library too. CSV, TSV and table output always show the underlying text, since flat formats cannot represent nested structures.
For other TEXT columns that merely happen to contain a JSON string, you can use the ``--json-cols`` option to automatically detect these JSON columns and output them as nested JSON data:
.. code-block:: bash

View file

@ -1564,12 +1564,13 @@ You can add a new column to a table using the ``.add_column(col_name, col_type)`
db.table("dogs").add_column("dob", datetime.date)
db.table("dogs").add_column("image", "BLOB")
db.table("dogs").add_column("website") # str by default
db.table("dogs").add_column("friends", "JSON")
You can specify the ``col_type`` argument either using a SQLite type as a string, or by directly passing a Python type e.g. ``str`` or ``float``.
The ``col_type`` is optional - if you omit it the type of ``TEXT`` will be used.
SQLite types you can specify are ``"TEXT"``, ``"INTEGER"``, ``"FLOAT"``, ``"REAL"`` or ``"BLOB"``.
SQLite types you can specify are ``"TEXT"``, ``"INTEGER"``, ``"FLOAT"``, ``"REAL"``, ``"BLOB"`` or ``"JSON"``. A column declared as ``"JSON"`` will be automatically decoded back into a Python object (rather than a JSON string) whenever it is read, both by the Python library and by the :ref:`CLI <cli_json_values>`.
If you pass a Python type, it will be mapped to SQLite types as shown here::