<indexterm>
<primary>json_strip_nulls</primary>
</indexterm>
- <function>json_strip_nulls</function> ( <type>json</type> )
+ <function>json_strip_nulls</function> ( <parameter>target</parameter> <type>jsonb</type>, <optional>,<parameter>strip_in_arrays</parameter> <type>boolean</type> </optional> )
<returnvalue>json</returnvalue>
</para>
<para role="func_signature">
<indexterm>
<primary>jsonb_strip_nulls</primary>
</indexterm>
- <function>jsonb_strip_nulls</function> ( <type>jsonb</type> )
+ <function>jsonb_strip_nulls</function> ( <parameter>target</parameter> <type>jsonb</type>, <optional>,<parameter>strip_in_arrays</parameter> <type>boolean</type> </optional> )
<returnvalue>jsonb</returnvalue>
</para>
<para>
Deletes all object fields that have null values from the given JSON
- value, recursively. Null values that are not object fields are
- untouched.
+ value, recursively.
+ If <parameter>strip_in_arrays</parameter> is true (the default is false),
+ null array elements are also stripped.
+ Otherwise they are not stripped. Bare null values are never stripped.
</para>
<para>
<literal>json_strip_nulls('[{"f1":1, "f2":null}, 2, null, 3]')</literal>
<returnvalue>[{"f1":1},2,null,3]</returnvalue>
- </para></entry>
+ </para>
+ <para>
+ <literal>jsonb_strip_nulls('[1,2,null,3,4]', true);</literal>
+ <returnvalue>[1,2,3,4]</returnvalue>
+ </para>
+ </entry>
</row>
<row>
STRICT STABLE PARALLEL SAFE
AS 'jsonb_path_query_first_tz';
+CREATE OR REPLACE FUNCTION
+ jsonb_strip_nulls(target jsonb, strip_in_arrays boolean DEFAULT false)
+RETURNS jsonb
+LANGUAGE INTERNAL
+STRICT STABLE PARALLEL SAFE
+AS 'jsonb_strip_nulls';
+
+CREATE OR REPLACE FUNCTION
+ json_strip_nulls(target json, strip_in_arrays boolean DEFAULT false)
+RETURNS json
+LANGUAGE INTERNAL
+STRICT STABLE PARALLEL SAFE
+AS 'json_strip_nulls';
+
-- default normalization form is NFC, per SQL standard
CREATE OR REPLACE FUNCTION
"normalize"(text, text DEFAULT 'NFC')
JsonLexContext *lex;
StringInfo strval;
bool skip_next_null;
+ bool strip_in_arrays;
} StripnullState;
/* structure for generalized json/jsonb value passing */
{
StripnullState *_state = (StripnullState *) state;
- if (_state->strval->data[_state->strval->len - 1] != '[')
+ /* If strip_in_arrays is enabled and this is a null, mark it for skipping */
+ if (isnull && _state->strip_in_arrays)
+ {
+ _state->skip_next_null = true;
+ return JSON_SUCCESS;
+ }
+
+ /* Only add a comma if this is not the first valid element */
+ if (_state->strval->len > 0 &&
+ _state->strval->data[_state->strval->len - 1] != '[')
+ {
appendStringInfoCharMacro(_state->strval, ',');
+ }
return JSON_SUCCESS;
}
json_strip_nulls(PG_FUNCTION_ARGS)
{
text *json = PG_GETARG_TEXT_PP(0);
+ bool strip_in_arrays = PG_NARGS() == 2 ? PG_GETARG_BOOL(1) : false;
StripnullState *state;
JsonLexContext lex;
JsonSemAction *sem;
state->lex = makeJsonLexContext(&lex, json, true);
state->strval = makeStringInfo();
state->skip_next_null = false;
+ state->strip_in_arrays = strip_in_arrays;
sem->semstate = state;
sem->object_start = sn_object_start;
}
/*
- * SQL function jsonb_strip_nulls(jsonb) -> jsonb
+ * SQL function jsonb_strip_nulls(jsonb, bool) -> jsonb
*/
Datum
jsonb_strip_nulls(PG_FUNCTION_ARGS)
{
Jsonb *jb = PG_GETARG_JSONB_P(0);
+ bool strip_in_arrays = false;
JsonbIterator *it;
JsonbParseState *parseState = NULL;
JsonbValue *res = NULL;
JsonbIteratorToken type;
bool last_was_key = false;
+ if (PG_NARGS() == 2)
+ strip_in_arrays = PG_GETARG_BOOL(1);
+
if (JB_ROOT_IS_SCALAR(jb))
PG_RETURN_POINTER(jb);
(void) pushJsonbValue(&parseState, WJB_KEY, &k);
}
+ /* if strip_in_arrays is set, also skip null array elements */
+ if (strip_in_arrays)
+ if (type == WJB_ELEM && v.type == jbvNull)
+ continue;
+
if (type == WJB_VALUE || type == WJB_ELEM)
res = pushJsonbValue(&parseState, type, &v);
else
proname => 'to_json', provolatile => 's', prorettype => 'json',
proargtypes => 'anyelement', prosrc => 'to_json' },
{ oid => '3261', descr => 'remove object fields with null values from json',
- proname => 'json_strip_nulls', prorettype => 'json', proargtypes => 'json',
+ proname => 'json_strip_nulls', prorettype => 'json', proargtypes => 'json bool',
prosrc => 'json_strip_nulls' },
{ oid => '3947',
prorettype => 'jsonb', proargtypes => '',
prosrc => 'jsonb_build_object_noargs' },
{ oid => '3262', descr => 'remove object fields with null values from jsonb',
- proname => 'jsonb_strip_nulls', prorettype => 'jsonb', proargtypes => 'jsonb',
+ proname => 'jsonb_strip_nulls', prorettype => 'jsonb', proargtypes => 'jsonb bool',
prosrc => 'jsonb_strip_nulls' },
{ oid => '3478',
{"a":{},"d":{}}
(1 row)
+-- json_strip_nulls (strip_in_arrays=true)
+select json_strip_nulls(null, true);
+ json_strip_nulls
+------------------
+
+(1 row)
+
+select json_strip_nulls('1', true);
+ json_strip_nulls
+------------------
+ 1
+(1 row)
+
+select json_strip_nulls('"a string"', true);
+ json_strip_nulls
+------------------
+ "a string"
+(1 row)
+
+select json_strip_nulls('null', true);
+ json_strip_nulls
+------------------
+ null
+(1 row)
+
+select json_strip_nulls('[1,2,null,3,4]', true);
+ json_strip_nulls
+------------------
+ [1,2,3,4]
+(1 row)
+
+select json_strip_nulls('{"a":1,"b":null,"c":[2,null,3],"d":{"e":4,"f":null}}', true);
+ json_strip_nulls
+-------------------------------
+ {"a":1,"c":[2,3],"d":{"e":4}}
+(1 row)
+
+select json_strip_nulls('[1,{"a":1,"b":null,"c":2},3]', true);
+ json_strip_nulls
+---------------------
+ [1,{"a":1,"c":2},3]
+(1 row)
+
+-- an empty object is not null and should not be stripped
+select json_strip_nulls('{"a": {"b": null, "c": null}, "d": {} }', true);
+ json_strip_nulls
+------------------
+ {"a":{},"d":{}}
+(1 row)
+
-- json to tsvector
select to_tsvector('{"a": "aaa bbb ddd ccc", "b": ["eee fff ggg"], "c": {"d": "hhh iii"}}'::json);
to_tsvector
{"a": {}, "d": {}}
(1 row)
+-- jsonb_strip_nulls (strip_in_arrays=true)
+select jsonb_strip_nulls(null, true);
+ jsonb_strip_nulls
+-------------------
+
+(1 row)
+
+select jsonb_strip_nulls('1', true);
+ jsonb_strip_nulls
+-------------------
+ 1
+(1 row)
+
+select jsonb_strip_nulls('"a string"', true);
+ jsonb_strip_nulls
+-------------------
+ "a string"
+(1 row)
+
+select jsonb_strip_nulls('null', true);
+ jsonb_strip_nulls
+-------------------
+ null
+(1 row)
+
+select jsonb_strip_nulls('[1,2,null,3,4]', true);
+ jsonb_strip_nulls
+-------------------
+ [1, 2, 3, 4]
+(1 row)
+
+select jsonb_strip_nulls('{"a":1,"b":null,"c":[2,null,3],"d":{"e":4,"f":null}}', true);
+ jsonb_strip_nulls
+--------------------------------------
+ {"a": 1, "c": [2, 3], "d": {"e": 4}}
+(1 row)
+
+select jsonb_strip_nulls('[1,{"a":1,"b":null,"c":2},3]', true);
+ jsonb_strip_nulls
+--------------------------
+ [1, {"a": 1, "c": 2}, 3]
+(1 row)
+
+-- an empty object is not null and should not be stripped
+select jsonb_strip_nulls('{"a": {"b": null, "c": null}, "d": {} }', true);
+ jsonb_strip_nulls
+--------------------
+ {"a": {}, "d": {}}
+(1 row)
+
select jsonb_pretty('{"a": "test", "b": [1, 2, 3], "c": "test3", "d":{"dd": "test4", "dd2":{"ddd": "test5"}}}');
jsonb_pretty
----------------------------
-- an empty object is not null and should not be stripped
select json_strip_nulls('{"a": {"b": null, "c": null}, "d": {} }');
+-- json_strip_nulls (strip_in_arrays=true)
+
+select json_strip_nulls(null, true);
+
+select json_strip_nulls('1', true);
+
+select json_strip_nulls('"a string"', true);
+
+select json_strip_nulls('null', true);
+
+select json_strip_nulls('[1,2,null,3,4]', true);
+
+select json_strip_nulls('{"a":1,"b":null,"c":[2,null,3],"d":{"e":4,"f":null}}', true);
+
+select json_strip_nulls('[1,{"a":1,"b":null,"c":2},3]', true);
+
+-- an empty object is not null and should not be stripped
+select json_strip_nulls('{"a": {"b": null, "c": null}, "d": {} }', true);
+
-- json to tsvector
select to_tsvector('{"a": "aaa bbb ddd ccc", "b": ["eee fff ggg"], "c": {"d": "hhh iii"}}'::json);
-- an empty object is not null and should not be stripped
select jsonb_strip_nulls('{"a": {"b": null, "c": null}, "d": {} }');
+-- jsonb_strip_nulls (strip_in_arrays=true)
+
+select jsonb_strip_nulls(null, true);
+
+select jsonb_strip_nulls('1', true);
+
+select jsonb_strip_nulls('"a string"', true);
+
+select jsonb_strip_nulls('null', true);
+
+select jsonb_strip_nulls('[1,2,null,3,4]', true);
+
+select jsonb_strip_nulls('{"a":1,"b":null,"c":[2,null,3],"d":{"e":4,"f":null}}', true);
+
+select jsonb_strip_nulls('[1,{"a":1,"b":null,"c":2},3]', true);
+
+-- an empty object is not null and should not be stripped
+select jsonb_strip_nulls('{"a": {"b": null, "c": null}, "d": {} }', true);
select jsonb_pretty('{"a": "test", "b": [1, 2, 3], "c": "test3", "d":{"dd": "test4", "dd2":{"ddd": "test5"}}}');
select jsonb_pretty('[{"f1":1,"f2":null},2,null,[[{"x":true},6,7],8],3]');