Re: BUG #19735: `jsonb_object_agg_unique_strict` drops a JSONB `null` value as if it were SQL NULL

From: Dmitry Dolgov <9erthalion6(at)gmail(dot)com>
To: shihao zhong <zhong950419(at)gmail(dot)com>
Cc: pgsql-bugs(at)lists(dot)postgresql(dot)org, theshallow27(at)gmail(dot)com
Subject: Re: BUG #19735: `jsonb_object_agg_unique_strict` drops a JSONB `null` value as if it were SQL NULL
Date: 2026-10-07 09:58:43
Message-ID: asYJhYbXXBPV_D5x@ddolgov-thinkpadt14sgen1.rmtde.csb
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-bugs

> On Sun, Oct 04, 2026 at 03:38:11PM -0400, shihao zhong wrote:
>
> I can reproduce this on master. The same happens with all the
> skip_nulls paths, such as jsonb_object_agg_strict(), and JSON_OBJECT()
> and JSON_OBJECTAGG() using ABSENT ON NULL RETURNING jsonb. The jsonb
> array versions keep the value, jsonb_agg_strict('null'::jsonb) returns
> [null].
>
> Is dropping JSON nulls here intended? I looked at the old threads
> where skip_nulls was discussed [1][2], they are only about SQL NULLs.
> The docs just say "null".

Hm, that's annoying. My gut feeling is that for jsonb it was intended to
skip JSON nulls -- the aggregation functions prepares a state first time
to use it on the subsequent rounds, and JsonbParseState.skip_nulls
inside it clearly refers to JSON nulls:

bool skip_nulls; /* Skip null object fields */

It also makes sense from the user perspective, since applications that
use jsonb more often have to deal with JSON nulls rather than SQL NULLs.
So it's reasonable to have functionality to deal with a frequent case,
instead of requiring to call jsonb_typeof on every element.

Now, for json version it seems to be different, as it's state
JsonAggState does not have anything like that, and consequently refers
to the problem as "NULL values".

In the end we have two problems at hand:

* The aggregation functions documentation needs to be more clear which
nulls are meant there. Currently it's JSON null and SQL NULL for jsonb
functions, and SQL NULL for json functions.

* It would be great to unify the experience for both jsonb and json
functions. Unfortunately it looks like independently from the decision
(whether to make all functions skip JSON nulls and SQL NULLs or SQL
NULLs only), the solution probably would not be pretty, as there will
be need to categorize every incoming element. I'm inclined to make
both sets of functions to skip both JSON null and SQL NULL.

In response to

Browse pgsql-bugs by date

  From Date Subject
Next Message Zhijie Hou 2026-10-07 10:08:36 Re: Streaming decoding fails with "unexpected table_index_fetch_tuple call during logical decoding" when a relation has a TOASTed conbin (follow-up to BUG #18641)
Previous Message Rahul 2026-10-07 09:14:21 Re: BUG #19733: Row not visible to a new snapshot after its transactional logical decoding message has been streamed