Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1w3ZB0-001Lpg-2Z for pgsql-hackers@arkaria.postgresql.org; Fri, 20 Mar 2026 12:42:07 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1w3ZAz-005wg5-0u for pgsql-hackers@arkaria.postgresql.org; Fri, 20 Mar 2026 12:42:05 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1w3ZAy-005wfx-2N for pgsql-hackers@lists.postgresql.org; Fri, 20 Mar 2026 12:42:05 +0000 Received: from mail-qk1-x731.google.com ([2607:f8b0:4864:20::731]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1w3ZAx-00000000AN7-0HyU for pgsql-hackers@postgresql.org; Fri, 20 Mar 2026 12:42:04 +0000 Received: by mail-qk1-x731.google.com with SMTP id af79cd13be357-8cfbbf35354so82437785a.0 for ; Fri, 20 Mar 2026 05:42:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=dunslane-net.20230601.gappssmtp.com; s=20230601; t=1774010522; x=1774615322; darn=postgresql.org; h=content-transfer-encoding:in-reply-to:autocrypt:content-language :from:references:cc:to:subject:user-agent:mime-version:date :message-id:from:to:cc:subject:date:message-id:reply-to; bh=dEFoKY+PK1pfcsv9shqI6c+clMpIprOmujxQ9/FS05g=; b=FexOXmco5ddlDDCsN+5y/f+YWgQz+JCNoYj0YGPjrnog8gWWzkg3OwyY3rLaitoB9u kIaEC+L1Uf4Fm9mKuC+wFw+9laGPU10Dtvomx3gXeXYLJ9yeLN2nkKla2c/Lh6FZI1ot afqs3RpUc/+H01p/PT8CDeAy4rXIgUF9Km/uM2I02I2kbkJhKBiappHDWhfcSZRaADjh B9tlpB13oQ2fD7M9Ieq9P5Qj4Vd/2KMXGng3ACLiZqjW/BxydDtXX31Iw0gn0QWdelB3 za7szO859grqEjMHAKCYQDzHCnBCYKY2tdOHy6Bze/UwW4XO6180iSaLYiWvMoFQOdw/ 8c/A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774010522; x=1774615322; h=content-transfer-encoding:in-reply-to:autocrypt:content-language :from:references:cc:to:subject:user-agent:mime-version:date :message-id:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=dEFoKY+PK1pfcsv9shqI6c+clMpIprOmujxQ9/FS05g=; b=fXVT7T3SwRmAa2Se5Or2sggUYELmIHCS+12isKLN8yCQ9EHjnl1juUD+N5gvmXWKOZ QanTi4u49jTX64bA2FPYlM2fWd0QUQzN8CzKUajC6pWeZZ/EX0/6DCVxQzY5xqHTSkak odnMzZp+CzEXNbjisRgA3wN7oRFoPf2WKBY4WuK6hp0LaMM+bn0OWxWp9w/z8+yRT2Mv LKjIyFRH9WvYoAaOM6WIN4dJ7a5CU9KcW79eXLeCYaNtV7d0SsK4meXz3doBkBit5W/y rYw6mQIZLbz4MmR0L7JeL4ZlfUWhPFzroUOUJfzZ8W2y0FxqSEBjHQn+uxunzyrdOKRL KAgw== X-Forwarded-Encrypted: i=1; AJvYcCVh1sk8Gza8NQX5HN1QSmAp6JPc/glVaH7TAPZf1m4ykqnb03YSdDSmTDcI/J42ULocR65mD6cVVHlT60jF@postgresql.org X-Gm-Message-State: AOJu0YwH/xSDVNLWH2PkiU2bmWLtnw7AeDwwJ5ZGWdoFpHokKFQMNl3F E0q/U7PeeOqA8XFv36d77HLFIGwm/baj8kaxXfcFFKJ/FEocoatsn7HXjYUq0Idwp7E= X-Gm-Gg: ATEYQzyA9O5xTK7/BzkYEKho3N3cX/7LdUF85A3or+d4FKMlACsmSBJnfrg+SdFHe31 jgtZE8esGf4vmlGm8QNg4tyzK+4Km1rubpS9mo8iCxoXG+Re8BZAdYbowiCrs+goEMA3qvgKFLM 7thJo6cjD9O904Ao0lRdDEEDWquCZYaEpNN+UDoAnSd+CtwAdYGv0ZQDCYXX1QpKhF7c3Uoe/Gb VdsLvcQ2QVD2/NX8y9ybPCtudOyYXSzpEHYaPWn/yebM4OCAVvvlcd5K+7eToMoNadw4nhvsBaZ HsapCp3u2iOne5w3RJjR8Y8eVGewSlcOuPgvfEfXP/GlhjqFzQCHZdZhKmef8n1LwXCuiNvkOb7 1CqPXcktYPm1VwMQ0CcH5NFsAHcEhmEcHkgsSfVaY9bcQWquqx6c/Q8vtJK6y5l3Jqsj5bh312C 35sD0el5SGmgAxVogQVSoe8nrGZXglwA== X-Received: by 2002:a05:620a:6647:b0:8cf:d3a9:60d4 with SMTP id af79cd13be357-8cfd3a98aaemr25768985a.5.1774010521848; Fri, 20 Mar 2026 05:42:01 -0700 (PDT) Received: from ?IPV6:2605:a601:a6b0:500::1cb? ([2605:a601:a6b0:500::1cb]) by smtp.googlemail.com with ESMTPSA id af79cd13be357-8cfc908d8c4sm148342785a.22.2026.03.20.05.41.56 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Fri, 20 Mar 2026 05:42:00 -0700 (PDT) Message-ID: <2732ec01-112c-40ae-8b17-a6df5f30b266@dunslane.net> Date: Fri, 20 Mar 2026 08:41:55 -0400 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: Emitting JSON to file using COPY TO To: Joe Conway , jian he , Daniel Verite Cc: Masahiko Sawada , Junwang Zhao , Florents Tselai , "Andrey M. Borodin" , Dean Rasheed , Davin Shearer , PostgreSQL development References: <964a3377-d957-4a06-ad02-8228aefa65fc@dunslane.net> <8428eb0f-f467-4cbd-a510-5be4f29b9ad7@dunslane.net> <90984087-723c-48e6-88ca-661ed15b2dd6@joeconway.com> From: Andrew Dunstan Content-Language: en-US Autocrypt: addr=andrew@dunslane.net; keydata= xsBNBE7KWFkBCAClridxur2AIc7eW2AR7izbfp3EnNefie2HbLF0izW5Ik5UjX2HBXBx4syI gY6b0ugohXrr274+baoAlvSbq6cAoQuEVrk5IZFzt20b1Xkx65FwGSEj526yiKLocqkJceSq Xr9xcA5SGY+FZv441chh5SU92v4q6z+6LPpoHOh97ptAVXZYNTtU0LevyvD5lja0TzbvJm6C eFXitJfnm1pLEr0DGJCR/iUOl/N62Kh4855zZC7NHIjQHPOvV5Stz/l5ilDhvGVk+xkXFPys SjZoUr1rXhYLpiyi5sR0X9FHXT0KnGuz1F5ERO7ZTLSSQ6fJwPj6gOk9K+vvoKvoeql5ABEB AAHNJEFuZHJldyBEdW5zdGFuIDxhbmRyZXdAZHVuc2xhbmUubmV0PsLAlwQTAQgAQQIbAwIX gAIZAQULCQgHAwUVCgkICwUWAgMBAAIeBRYhBOQ+WEYd/Hy/RGkVpZn6f8tZ/DuBBQJoGNGd BQkdEO8nAAoJEJn6f8tZ/DuBq74H/jkTR4Zi3stbw+xC7v2u3QozssK7MYPL2AsVfh7OealS h182fiWXpfvmmAB7WUHbhk9GC2RAOnHI/2d2jgKaMLAHsGYOT0YopTVIwRY43fCw/mK67yxc wmDcX+zyKfLaivNbf5A7QPLNwda98bEAMSJ8Sn652Uc6cA8t3uKGsVzbRBQOoYzjgvBCfSrE 9ql3PDNg0l4BfAqabd2f70ZUm9VAMEPrgv/v2xI7M2XiL4g5BVmqLCOwxLM8RMCotCuoweUr VO43DeBCIDwLxotMJKvGWDjBzQYlU1NPUAtNcz/gN9ITUe1VUGjyvGj4u1lxBOcQQUw7l1+T 5moZ4iZxXzvOwE0ETspYWQEIANGc4zQULOxhbqO2dyD51YhqCNRmm9oKWaqf+wmW4tpDe/VV cxAnNizd4LWCHfzpb5cHAtGkOPePMfzWVf6nvdF7d3eglbtf59+zG7O7llV0xSSoFiieQBsr GvqDInXYX/4mRRXMtyhM353/tixC9RWLs1oofyYmCPPXXY7h9R7en3B8BoVrRFcdzlIY/NFN hFGW/9dkEiGjgna2Rk6e15kln4ZvFBWUg23p93w/pqXcxY6+k/8TEk+C4R+M6w7o2PLGOjdZ +kPiUcw5H85zf/yZJwQXzisXaNduwWB6Vads9YC9dj6kPR1c4VGRqAaYL++LAEOqrlvm2Tvq QqZRtnEAEQEAAcLAfAQYAQgAJgIbDBYhBOQ+WEYd/Hy/RGkVpZn6f8tZ/DuBBQJoGNI2BQkd EODdAAoJEJn6f8tZ/DuBfw0IAKTsfD40teP/pp+bsLLMSxPXUYrrprTj7WFB5v61p6dkpSr/ qXmMlyahdxQFaPmfVgVirB1Vk/kHiWNnnGjfUV9nB2Zg9LI0Xb9/ts3LsUiRWXzG3tkMY6XL vsVOxW4XFRND9l2q+WW93aZ1DZl+fqWfYgMvsusFRhmGFOKTRfKPta2Pkv+AhA24N4+PrR5p bU4k2MO8PAGiK8eaYKGFG1bHKuAvoDoF7WXJ3FHxuWqLnKEt4dfOLm5pAe3zq1Lt6q8azT9i QWGpSAK5vQUWQHBHpiDjdPeqKZ6HiAXIIKfSmb+jrvXBqoP+D6/K7rUjG2aXiRtTIAXms9sm VRu7cmw= In-Reply-To: <90984087-723c-48e6-88ca-661ed15b2dd6@joeconway.com> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On 2026-03-19 Th 12:06 PM, Joe Conway wrote: > On 3/19/26 11:02, Andrew Dunstan wrote: >> >> On 2026-03-18 We 9:58 PM, jian he wrote: >>> On Wed, Mar 18, 2026 at 10:37 PM Daniel Verite >>> 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: >>> >>>    >>>     JSON Format >>>      >>>        When the json format is used, data is >>> exported with one JSON object per line, >>>        where each line corresponds to a single record. >>>        The json format has no standard way to >>> distinguish between an SQL NULL and a JSON >>> null literal. >>>        In the examples that follow, the following table containing JSON >>> data will be used: >>> >>> CREATE TABLE my_test (a jsonb, b int); >>> INSERT INTO my_test VALUES ('null', 1), (NULL, 1); >>> >>> >>>      When exporting this table using the json >>> format: >>> >>> COPY my_test TO STDOUT (FORMAT JSON); >>> >>>      In the resulting output, both the SQL NULL and >>> the JSON null are rendered identically: >>> >>> {"a":null,"b":1} >>> {"a":null,"b":1} >>> >>>     >>>    >>> >>> >>> >>> what do you think? >>> >>> >>> >> >> I can live with that, if others can. > > +1 > WFM > pushed with that addition. cheers andrew -- Andrew Dunstan EDB: https://www.enterprisedb.com