Commit e56ec50c authored by Tom Lane's avatar Tom Lane

Use ISO 8601 format for dates converted to JSON, too.

Commit f30015b6 made this happen for
timestamp and timestamptz, but it seems pretty inconsistent to not
do it for simple dates as well.

(In passing, I re-pgindent'd json.c.)
parent 3e9f70f1
......@@ -120,7 +120,7 @@
<listitem>
<para>
When converting values of type <type>timestamp</>
When converting values of type <type>date</>, <type>timestamp</>
or <type>timestamptz</>
to <link linkend="datatype-json"><type>JSON</type></link>, render the
values in a format compliant with ISO 8601 (Andrew Dunstan)
......@@ -129,7 +129,10 @@
<para>
Previously such values were rendered according to the current
<xref linkend="guc-datestyle"> setting; but many JSON processors
require timestamps to be in ISO 8601 format.
require timestamps to be in ISO 8601 format. If necessary, the
previous behavior can be obtained by explicitly casting the datetime
value to <type>text</> before passing it to the JSON conversion
function.
</para>
</listitem>
......
......@@ -25,6 +25,7 @@
#include "parser/parse_coerce.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/date.h"
#include "utils/datetime.h"
#include "utils/lsyscache.h"
#include "utils/json.h"
......@@ -55,8 +56,9 @@ typedef enum /* type categories for datum_to_json */
JSONTYPE_NULL, /* null, so we didn't bother to identify */
JSONTYPE_BOOL, /* boolean (built-in types only) */
JSONTYPE_NUMERIC, /* numeric (ditto) */
JSONTYPE_TIMESTAMP, /* we use special formatting for timestamp */
JSONTYPE_TIMESTAMPTZ, /* ... and timestamptz */
JSONTYPE_DATE, /* we use special formatting for datetimes */
JSONTYPE_TIMESTAMP,
JSONTYPE_TIMESTAMPTZ,
JSONTYPE_JSON, /* JSON itself (and JSONB) */
JSONTYPE_ARRAY, /* array */
JSONTYPE_COMPOSITE, /* composite */
......@@ -1267,6 +1269,10 @@ json_categorize_type(Oid typoid,
*tcategory = JSONTYPE_NUMERIC;
break;
case DATEOID:
*tcategory = JSONTYPE_DATE;
break;
case TIMESTAMPOID:
*tcategory = JSONTYPE_TIMESTAMP;
break;
......@@ -1388,6 +1394,30 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
}
pfree(outputstr);
break;
case JSONTYPE_DATE:
{
DateADT date;
struct pg_tm tm;
char buf[MAXDATELEN + 1];
date = DatumGetDateADT(val);
/* XSD doesn't support infinite values */
if (DATE_NOT_FINITE(date))
ereport(ERROR,
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
errmsg("date out of range"),
errdetail("JSON does not support infinite date values.")));
else
{
j2date(date + POSTGRES_EPOCH_JDATE,
&(tm.tm_year), &(tm.tm_mon), &(tm.tm_mday));
EncodeDateOnly(&tm, USE_XSD_DATES, buf);
}
appendStringInfo(result, "\"%s\"", buf);
}
break;
case JSONTYPE_TIMESTAMP:
{
Timestamp timestamp;
......@@ -1410,7 +1440,7 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
errmsg("timestamp out of range")));
appendStringInfo(result,"\"%s\"",buf);
appendStringInfo(result, "\"%s\"", buf);
}
break;
case JSONTYPE_TIMESTAMPTZ:
......@@ -1437,7 +1467,7 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
errmsg("timestamp out of range")));
appendStringInfo(result,"\"%s\"",buf);
appendStringInfo(result, "\"%s\"", buf);
}
break;
case JSONTYPE_JSON:
......@@ -2305,20 +2335,21 @@ escape_json(StringInfo buf, const char *str)
appendStringInfoString(buf, "\\\"");
break;
case '\\':
/*
* Unicode escapes are passed through as is. There is no
* requirement that they denote a valid character in the
* server encoding - indeed that is a big part of their
* usefulness.
*
* All we require is that they consist of \uXXXX where
* the Xs are hexadecimal digits. It is the responsibility
* of the caller of, say, to_json() to make sure that the
* unicode escape is valid.
* All we require is that they consist of \uXXXX where the Xs
* are hexadecimal digits. It is the responsibility of the
* caller of, say, to_json() to make sure that the unicode
* escape is valid.
*
* In the case of a jsonb string value being escaped, the
* only unicode escape that should be present is \u0000,
* all the other unicode escapes will have been resolved.
* In the case of a jsonb string value being escaped, the only
* unicode escape that should be present is \u0000, all the
* other unicode escapes will have been resolved.
*/
if (p[1] == 'u' &&
isxdigit((unsigned char) p[2]) &&
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment