Re: Emitting JSON to file using COPY TO

From: jian he <jian(dot)universality(at)gmail(dot)com>
To: Daniel Verite <daniel(at)manitou-mail(dot)org>
Cc: Andrew Dunstan <andrew(at)dunslane(dot)net>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, Joe Conway <mail(at)joeconway(dot)com>, Junwang Zhao <zhjwpku(at)gmail(dot)com>, Florents Tselai <florents(dot)tselai(at)gmail(dot)com>, "Andrey M(dot) Borodin" <x4mmm(at)yandex-team(dot)ru>, Dean Rasheed <dean(dot)a(dot)rasheed(at)gmail(dot)com>, Davin Shearer <davin(at)apache(dot)org>, PostgreSQL development <pgsql-hackers(at)postgresql(dot)org>
Subject: Re: Emitting JSON to file using COPY TO
Date: 2026-03-19 01:58:05
Message-ID: CACJufxGAQk5cr3zcqX-PfN-9S+qnJgLL+OmNGhKeG_iG5mvddw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-general pgsql-hackers

On Wed, Mar 18, 2026 at 10:37 PM Daniel Verite <daniel(at)manitou-mail(dot)org> wrote:
>
> Currently there's no difference in output between the null
> json value and the SQL null.
>
> postgres=# create table tbl (j jsonb);
> postgres=# insert into tbl values('null');
> postgres=# insert into tbl values(null);
> postgres=# copy tbl to stdout with (format json);
> {"j":null}
> {"j":null}
>
> Does it have to be that way or are there valid distinct outputs
> that we could use to avoid this ambiguity?
>

This is an existing (quite old) behavior of
composite_to_json->datum_to_json_internal, IMHO.

```
if (is_null)
{
appendBinaryStringInfo(result, "null", strlen("null"));
return;
}
```
produce the same results as
```
case JSONTYPE_JSON:
/* JSON and JSONB output will already be escaped */
outputstr = OidOutputFunctionCall(outfuncoid, val);
appendStringInfoString(result, outputstr);
pfree(outputstr);
break;
```

Therefore I intended to document it as below:

<refsect2 id="sql-copy-json-format" xreflabel="JSON Format">
<title>JSON Format</title>
<para>
When the <literal>json</literal> format is used, data is
exported with one JSON object per line,
where each line corresponds to a single record.
The <literal>json</literal> format has no standard way to
distinguish between an SQL <literal>NULL</literal> and a JSON
<literal>null</literal> literal.
In the examples that follow, the following table containing JSON
data will be used:
<programlisting>
CREATE TABLE my_test (a jsonb, b int);
INSERT INTO my_test VALUES ('null', 1), (NULL, 1);
</programlisting>

When exporting this table using the <literal>json</literal> format:
<programlisting>
COPY my_test TO STDOUT (FORMAT JSON);
</programlisting>
In the resulting output, both the SQL <literal>NULL</literal> and
the JSON <literal>null</literal> are rendered identically:
<screen>
{"a":null,"b":1}
{"a":null,"b":1}
</screen>
</para>
</refsect2>

what do you think?

--
jian
https://www.enterprisedb.com/

In response to

Responses

Browse pgsql-general by date

  From Date Subject
Next Message Andrew Dunstan 2026-03-19 15:02:21 Re: Emitting JSON to file using COPY TO
Previous Message Greg Hennessy 2026-03-18 15:56:20 Re: help debugging an issue with selectivity

Browse pgsql-hackers by date

  From Date Subject
Next Message Robert Haas 2026-03-19 02:25:33 Re: Feature freeze timezone change request
Previous Message Tatsuo Ishii 2026-03-19 01:39:30 Re: Row pattern recognition