diff options
author | Andrew Dunstan <andrew@dunslane.net> | 2014-06-03 13:56:53 -0400 |
---|---|---|
committer | Andrew Dunstan <andrew@dunslane.net> | 2014-06-03 13:56:53 -0400 |
commit | f30015b6d794c15d52abbb3df3a65081fbefb1ed (patch) | |
tree | 6be9d4a73a40a628474f11f173252f16f72c6959 /src/backend/utils/adt/json.c | |
parent | 2dfa15de5510b3c19ffb92b512c39d5440a07b1e (diff) | |
download | postgresql-f30015b6d794c15d52abbb3df3a65081fbefb1ed.tar.gz postgresql-f30015b6d794c15d52abbb3df3a65081fbefb1ed.zip |
Output timestamps in ISO 8601 format when rendering JSON.
Many JSON processors require timestamp strings in ISO 8601 format in
order to convert the strings. When converting a timestamp, with or
without timezone, to a JSON datum we therefore now use such a format
rather than the type's default text output, in functions such as
to_json().
This is a change in behaviour from 9.2 and 9.3, as noted in the release
notes.
Diffstat (limited to 'src/backend/utils/adt/json.c')
-rw-r--r-- | src/backend/utils/adt/json.c | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/src/backend/utils/adt/json.c b/src/backend/utils/adt/json.c index a7364f30f84..2462111ecb3 100644 --- a/src/backend/utils/adt/json.c +++ b/src/backend/utils/adt/json.c @@ -24,6 +24,7 @@ #include "parser/parse_coerce.h" #include "utils/array.h" #include "utils/builtins.h" +#include "utils/formatting.h" #include "utils/lsyscache.h" #include "utils/json.h" #include "utils/jsonapi.h" @@ -53,6 +54,8 @@ 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_JSON, /* JSON itself (and JSONB) */ JSONTYPE_ARRAY, /* array */ JSONTYPE_COMPOSITE, /* composite */ @@ -60,6 +63,13 @@ typedef enum /* type categories for datum_to_json */ JSONTYPE_OTHER /* all else */ } JsonTypeCategory; +/* + * to_char formats to turn timestamps and timpstamptzs into json strings + * that are ISO 8601 compliant + */ +#define TS_ISO8601_FMT "\\\"YYYY-MM-DD\"T\"HH24:MI:SS.US\\\"" +#define TSTZ_ISO8601_FMT "\\\"YYYY-MM-DD\"T\"HH24:MI:SS.USOF\\\"" + static inline void json_lex(JsonLexContext *lex); static inline void json_lex_string(JsonLexContext *lex); static inline void json_lex_number(JsonLexContext *lex, char *s, bool *num_err); @@ -1262,6 +1272,14 @@ json_categorize_type(Oid typoid, *tcategory = JSONTYPE_NUMERIC; break; + case TIMESTAMPOID: + *tcategory = JSONTYPE_TIMESTAMP; + break; + + case TIMESTAMPTZOID: + *tcategory = JSONTYPE_TIMESTAMPTZ; + break; + case JSONOID: case JSONBOID: *tcategory = JSONTYPE_JSON; @@ -1375,6 +1393,29 @@ datum_to_json(Datum val, bool is_null, StringInfo result, } pfree(outputstr); break; + case JSONTYPE_TIMESTAMP: + /* + * The timestamp format used here provides for quoting the string, + * so no escaping is required. + */ + jsontext = DatumGetTextP( + DirectFunctionCall2(timestamp_to_char, val, + CStringGetTextDatum(TS_ISO8601_FMT))); + outputstr = text_to_cstring(jsontext); + appendStringInfoString(result, outputstr); + pfree(outputstr); + pfree(jsontext); + break; + case JSONTYPE_TIMESTAMPTZ: + /* same comment as for timestamp above */ + jsontext = DatumGetTextP( + DirectFunctionCall2(timestamptz_to_char, val, + CStringGetTextDatum(TSTZ_ISO8601_FMT))); + outputstr = text_to_cstring(jsontext); + appendStringInfoString(result, outputstr); + pfree(outputstr); + pfree(jsontext); + break; case JSONTYPE_JSON: /* JSON and JSONB output will already be escaped */ outputstr = OidOutputFunctionCall(outfuncoid, val); |