ganeshashree opened a new pull request, #58034:
URL: https://github.com/apache/spark/pull/58034
### What changes were proposed in this pull request?
Implement the ANSI SQL:2016 `JSON_OBJECT` constructor function, which builds
a JSON object from key/value pairs and returns it as JSON text.
Syntax (a dedicated `primaryExpression` production, mirroring
`JSON_TABLE`/`JSON_ARRAY`, because the key/value list carries non-expression
syntax):
```
JSON_OBJECT ( [ { key VALUE value | key : value | key, value } [, ...] ]
[ { NULL | ABSENT } ON NULL ]
[ RETURNING string_type ] )
```
- New `JsonObjectExpr` Catalyst expression that serializes each value
through the same Jackson writer as `to_json`, so numbers, decimals, datetimes,
and nested
structs/arrays/maps render consistently.
- Three interchangeable key/value spellings are accepted and may be mixed:
`key VALUE
value` (ANSI), `key : value` (colon), and `key, value` (MySQL-style comma).
- Keys must be non-null strings; a null key is a runtime error.
- `(NULL | ABSENT) ON NULL`: `NULL ON NULL` (the standard default for
`JSON_OBJECT`)
keeps null-valued members as JSON `null`; `ABSENT ON NULL` omits them.
- `RETURNING`: defaults to `STRING` and is restricted to string types
(VARIANT deferred);
`CHAR`/`VARCHAR` are normalized to `STRING`.
- A nested JSON constructor is spliced in as raw JSON rather than quoted,
via the shared
`ImplicitlyFormattedAsJson` scaffolding.
- `JSON_OBJECT` and `ABSENT` added as non-reserved keywords (matching
`JSON_TABLE`/`JSON_VALUE`/`JSON_ARRAY`).
Examples:
```
SELECT json_object('id' VALUE 7, 'name' VALUE 'Ada'); --
{"id":7,"name":"Ada"}
SELECT json_object('id': 7, 'name': 'Ada'); --
{"id":7,"name":"Ada"} (colon)
SELECT json_object('id', 7, 'name', 'Ada'); --
{"id":7,"name":"Ada"} (comma)
SELECT json_object('id': 7, 'v': NULL); --
{"id":7,"v":null} (NULL ON NULL default)
SELECT json_object('id': 7, 'v': NULL ABSENT ON NULL); -- {"id":7}
SELECT json_object('a', json_object('b', 1)); -- {"a":{"b":1}}
(nested: spliced as JSON)
```
### Why are the changes needed?
Spark implements none of the ANSI SQL:2016 constructor JSON functions,
forcing users migrating from Oracle, SQL Server, MySQL, Trino, or BigQuery to
rewrite `JSON_OBJECT('k', v, ...)` as `to_json(named_struct('k', v, ...))`,
which is verbose and
does not carry the standard's `ON NULL` / `RETURNING` semantics.
### Does this PR introduce _any_ user-facing change?
Yes. It adds the new `JSON_OBJECT` SQL constructor function and the new
non-reserved
keywords `JSON_OBJECT` and `ABSENT`. There is no change to existing queries
(both
keywords remain usable as identifiers, as they are non-reserved).
### How was this patch tested?
- New `JsonObjectSuite`: the three key/value spellings and mixed usage, both
`ON NULL` modes, `RETURNING` (collated + CHAR/VARCHAR normalization),
nested-constructor splicing, null-key rejection, scalar/mixed/nested values,
and analysis-time type rejection.
- Golden-file coverage in `json-functions.sql` (`SQLQueryTestSuite`).
- Regenerated `keywords*.sql.out` for the new keywords; `checkError`
coverage for the new error conditions.
- New reference doc page `sql-ref-syntax-qry-select-json-object.md`.
### Was this patch authored or co-authored using generative AI tooling?
Generated-by: Claude Code (Opus 4.8)
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]