JSON_QUERY

Description

The JSON_QUERY function extracts the JSON value located by a SQL/JSON path from a JSON document and returns it as JSON text (a STRING). This is the SQL-standard way (SQL:2016) to pull an object, array, or scalar fragment out of JSON, and is commonly used to migrate queries from other systems such as Oracle, SQL Server, and Trino. Unlike JSON_TABLE, which produces rows in a FROM clause, JSON_QUERY is an expression that can appear anywhere a value is allowed.

Where JSON_VALUE returns a single scalar (and treats an object or array match as an error), JSON_QUERY returns the matched value serialized as JSON text, whether it is an object, an array, or a scalar.

This implementation supports simple, wildcard-free SQL/JSON paths only. The PASSING clause, path predicates and filters, and explicit lax / strict path modes defined by SQL:2016 are not supported.

Syntax

JSON_QUERY ( json_expr, path
             [ RETURNING data_type ]
             [ wrapper_behavior ]
             [ quotes_behavior ]
             [ empty_behavior ON EMPTY ]
             [ error_behavior ON ERROR ] )

wrapper_behavior
    { WITHOUT [ ARRAY ] WRAPPER
    | WITH [ CONDITIONAL | UNCONDITIONAL ] [ ARRAY ] WRAPPER }

quotes_behavior
    { KEEP QUOTES | OMIT QUOTES }

empty_behavior
    { NULL | ERROR | EMPTY ARRAY | EMPTY OBJECT }

error_behavior
    { NULL | ERROR | EMPTY ARRAY | EMPTY OBJECT }

Parameters

A path that matches an explicit JSON null is a present scalar value and returns the JSON text null (it is neither the ON EMPTY nor the ON ERROR case).

Returning a scalar under the default WITHOUT ARRAY WRAPPER is an intentional convenience: the matched scalar is emitted as JSON text (for example, JSON_QUERY('{"id":7}', '$.id') returns 7), whereas strict SQL:2016 treats a scalar without a wrapper as an error. The wrapper clauses behave the standard way: WITH CONDITIONAL ARRAY WRAPPER wraps a scalar in a one-element array (7 becomes [7]) while leaving a single object or array unwrapped, and WITH UNCONDITIONAL ARRAY WRAPPER always wraps.

Examples

-- Extract an object as JSON text
SELECT json_query('{"id":7,"addr":{"city":"NYC"}}', '$.addr');
+---------------------------------------------------+
|json_query({"id":7,"addr":{"city":"NYC"}}, $.addr) |
+---------------------------------------------------+
|{"city":"NYC"}                                     |
+---------------------------------------------------+

-- Extract an array
SELECT json_query('{"tags":["x","y"]}', '$.tags');
+-------------------------------------------+
|json_query({"tags":["x","y"]}, $.tags)     |
+-------------------------------------------+
|["x","y"]                                  |
+-------------------------------------------+

-- Wrap a scalar in an array with WITH ARRAY WRAPPER
-- (WITH ARRAY WRAPPER is a shorthand; the column name shows the canonical
--  WITH UNCONDITIONAL ARRAY WRAPPER form)
SELECT json_query('{"tags":["x","y"]}', '$.tags[0]' WITH ARRAY WRAPPER);
+----------------------------------------------------------------------------+
|json_query({"tags":["x","y"]}, $.tags[0] WITH UNCONDITIONAL ARRAY WRAPPER)  |
+----------------------------------------------------------------------------+
|["x"]                                                                       |
+----------------------------------------------------------------------------+

-- Strip the quotes from a scalar string with OMIT QUOTES
SELECT json_query('{"name":"Ada"}', '$.name' OMIT QUOTES);
+---------------------------------------------------+
|json_query({"name":"Ada"}, $.name OMIT QUOTES)     |
+---------------------------------------------------+
|Ada                                                |
+---------------------------------------------------+

-- A missing path defaults to NULL; supply a fallback with EMPTY ARRAY ON EMPTY
SELECT json_query('{"id":7}', '$.missing' EMPTY ARRAY ON EMPTY);
+---------------------------------------------------------+
|json_query({"id":7}, $.missing EMPTY ARRAY ON EMPTY)     |
+---------------------------------------------------------+
|[]                                                       |
+---------------------------------------------------------+

-- ERROR ON ERROR raises instead of returning a value
SELECT json_query('not json', '$.a' ERROR ON ERROR);
[JSON_QUERY_ON_ERROR.ERROR] ...