Andrew Tipton.
</entry>
<entry><type>json</type></entry>
<entry>
- Returns JSON object pointed to by <parameter>path_elems</parameter>.
+ Returns JSON value pointed to by <parameter>path_elems</parameter>.
</entry>
<entry><literal>json_extract_path('{"f2":{"f3":1},"f4":{"f5":99,"f6":"foo"}}','f4')</literal></entry>
<entry><literal>{"f5":99,"f6":"foo"}</literal></entry>
</entry>
<entry><type>text</type></entry>
<entry>
- Returns JSON object pointed to by <parameter>path_elems</parameter>.
+ Returns JSON value pointed to by <parameter>path_elems</parameter>.
</entry>
<entry><literal>json_extract_path_text('{"f2":{"f3":1},"f4":{"f5":99,"f6":"foo"}}','f4', 'f6')</literal></entry>
<entry><literal>foo</literal></entry>
</entry>
<entry><type>SETOF json</type></entry>
<entry>
- Expands a JSON array to a set of JSON elements.
+ Expands a JSON array to a set of JSON values.
</entry>
<entry><literal>json_array_elements('[1,true, [2,false]]')</literal></entry>
<entry>
</programlisting>
</entry>
</row>
+ <row>
+ <entry>
+ <indexterm>
+ <primary>json_typeof</primary>
+ </indexterm>
+ <literal>json_typeof(json)</literal>
+ </entry>
+ <entry><type>text</type></entry>
+ <entry>
+ Returns the type of the outermost JSON value as a text string. The types are
+ <literal>object</>, <literal>array</>, <literal>string</>, <literal>number</>,
+ <literal>boolean</>, and <literal>null</>. (See note below regarding the
+ distinction between a JSON <literal>null</> and a SQL NULL.)
+ </entry>
+ <entry><literal>json_typeof('-123.4')</literal></entry>
+ <entry><literal>number</literal></entry>
+ </row>
</tbody>
</tgroup>
</table>
</para>
</note>
+ <note>
+ <para>
+ The <literal>json_typeof</> function's <literal>null</> return value should not be confused
+ with a SQL NULL. While calling <literal>json_typeof('null'::json)</> will return <literal>null</>,
+ calling <literal>json_typeof(NULL::json)</> will return a SQL NULL.
+ </para>
+ </note>
+
<para>
See also <xref linkend="functions-aggregate"> about the aggregate
function <function>json_agg</function> which aggregates record
}
appendStringInfoCharMacro(buf, '\"');
}
+
+/*
+ * SQL function json_typeof(json) -> text
+ *
+ * Returns the type of the outermost JSON value as TEXT. Possible types are
+ * "object", "array", "string", "number", "boolean", and "null".
+ *
+ * Performs a single call to json_lex() to get the first token of the supplied
+ * value. This initial token uniquely determines the value's type. As our
+ * input must already have been validated by json_in() or json_recv(), the
+ * initial token should never be JSON_TOKEN_OBJECT_END, JSON_TOKEN_ARRAY_END,
+ * JSON_TOKEN_COLON, JSON_TOKEN_COMMA, or JSON_TOKEN_END.
+ */
+Datum
+json_typeof(PG_FUNCTION_ARGS)
+{
+ text *json = PG_GETARG_TEXT_P(0);
+
+ JsonLexContext *lex = makeJsonLexContext(json, false);
+ JsonTokenType tok;
+ char *type;
+
+ /* Lex exactly one token from the input and check its type. */
+ json_lex(lex);
+ tok = lex_peek(lex);
+ switch (tok)
+ {
+ case JSON_TOKEN_OBJECT_START:
+ type = "object";
+ break;
+ case JSON_TOKEN_ARRAY_START:
+ type = "array";
+ break;
+ case JSON_TOKEN_STRING:
+ type = "string";
+ break;
+ case JSON_TOKEN_NUMBER:
+ type = "number";
+ break;
+ case JSON_TOKEN_TRUE:
+ case JSON_TOKEN_FALSE:
+ type = "boolean";
+ break;
+ case JSON_TOKEN_NULL:
+ type = "null";
+ break;
+ default:
+ elog(ERROR, "unexpected json token: %d", tok);
+ }
+
+ PG_RETURN_TEXT_P(cstring_to_text(type));
+}
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 201310091
+#define CATALOG_VERSION_NO 201310101
#endif
DESCR("get record fields from a json object");
DATA(insert OID = 3961 ( json_populate_recordset PGNSP PGUID 12 1 100 0 0 f f f f f t s 3 0 2283 "2283 114 16" _null_ _null_ _null_ _null_ json_populate_recordset _null_ _null_ _null_ ));
DESCR("get set of records with fields from a json array of objects");
+DATA(insert OID = 3968 ( json_typeof PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 25 "114" _null_ _null_ _null_ _null_ json_typeof _null_ _null_ _null_ ));
+DESCR("get the type of a json value");
/* uuid */
DATA(insert OID = 2952 ( uuid_in PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2950 "2275" _null_ _null_ _null_ _null_ uuid_in _null_ _null_ _null_ ));
extern void escape_json(StringInfo buf, const char *str);
+extern Datum json_typeof(PG_FUNCTION_ARGS);
+
/* functions in jsonfuncs.c */
extern Datum json_object_field(PG_FUNCTION_ARGS);
extern Datum json_object_field_text(PG_FUNCTION_ARGS);
null \u0000 escape
(1 row)
+--json_typeof() function
+select value, json_typeof(value)
+ from (values (json '123.4'),
+ (json '-1'),
+ (json '"foo"'),
+ (json 'true'),
+ (json 'false'),
+ (json 'null'),
+ (json '[1, 2, 3]'),
+ (json '[]'),
+ (json '{"x":"foo", "y":123}'),
+ (json '{}'),
+ (NULL::json))
+ as data(value);
+ value | json_typeof
+----------------------+-------------
+ 123.4 | number
+ -1 | number
+ "foo" | string
+ true | boolean
+ false | boolean
+ null | null
+ [1, 2, 3] | array
+ [] | array
+ {"x":"foo", "y":123} | object
+ {} | object
+ |
+(11 rows)
+
null \u0000 escape
(1 row)
+--json_typeof() function
+select value, json_typeof(value)
+ from (values (json '123.4'),
+ (json '-1'),
+ (json '"foo"'),
+ (json 'true'),
+ (json 'false'),
+ (json 'null'),
+ (json '[1, 2, 3]'),
+ (json '[]'),
+ (json '{"x":"foo", "y":123}'),
+ (json '{}'),
+ (NULL::json))
+ as data(value);
+ value | json_typeof
+----------------------+-------------
+ 123.4 | number
+ -1 | number
+ "foo" | string
+ true | boolean
+ false | boolean
+ null | null
+ [1, 2, 3] | array
+ [] | array
+ {"x":"foo", "y":123} | object
+ {} | object
+ |
+(11 rows)
+
select json '{ "a": "the Copyright \u00a9 sign" }' ->> 'a' as correct_in_utf8;
select json '{ "a": "dollar \u0024 character" }' ->> 'a' as correct_everywhere;
select json '{ "a": "null \u0000 escape" }' ->> 'a' as not_unescaped;
+
+--json_typeof() function
+select value, json_typeof(value)
+ from (values (json '123.4'),
+ (json '-1'),
+ (json '"foo"'),
+ (json 'true'),
+ (json 'false'),
+ (json 'null'),
+ (json '[1, 2, 3]'),
+ (json '[]'),
+ (json '{"x":"foo", "y":123}'),
+ (json '{}'),
+ (NULL::json))
+ as data(value);