mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-03-31 20:20:44 +08:00
Allow json{b}_strip_nulls to remove null array elements
An additional paramater ("strip_in_arrays") is added to these functions. It defaults to false. If true, then null array elements are removed as well as null valued object fields. JSON that just consists of a single null is not affected. Author: Florents Tselai <florents.tselai@gmail.com> Discussion: https://postgr.es/m/4BCECCD5-4F40-4313-9E98-9E16BEB0B01D@gmail.com
This commit is contained in:
parent
5ead85fbc8
commit
4603903d29
@ -17345,25 +17345,32 @@ ERROR: value too long for type character(2)
|
||||
<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>
|
||||
|
@ -607,6 +607,20 @@ LANGUAGE INTERNAL
|
||||
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')
|
||||
|
@ -286,6 +286,7 @@ typedef struct StripnullState
|
||||
JsonLexContext *lex;
|
||||
StringInfo strval;
|
||||
bool skip_next_null;
|
||||
bool strip_in_arrays;
|
||||
} StripnullState;
|
||||
|
||||
/* structure for generalized json/jsonb value passing */
|
||||
@ -4460,8 +4461,19 @@ sn_array_element_start(void *state, bool isnull)
|
||||
{
|
||||
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;
|
||||
}
|
||||
@ -4493,6 +4505,7 @@ Datum
|
||||
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;
|
||||
@ -4503,6 +4516,7 @@ json_strip_nulls(PG_FUNCTION_ARGS)
|
||||
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;
|
||||
@ -4520,12 +4534,13 @@ json_strip_nulls(PG_FUNCTION_ARGS)
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
@ -4534,6 +4549,9 @@ jsonb_strip_nulls(PG_FUNCTION_ARGS)
|
||||
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);
|
||||
|
||||
@ -4564,6 +4582,11 @@ jsonb_strip_nulls(PG_FUNCTION_ARGS)
|
||||
(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
|
||||
|
@ -9269,7 +9269,7 @@
|
||||
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',
|
||||
@ -10205,7 +10205,7 @@
|
||||
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',
|
||||
|
@ -2504,6 +2504,56 @@ select json_strip_nulls('{"a": {"b": null, "c": null}, "d": {} }');
|
||||
{"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
|
||||
|
@ -4153,6 +4153,56 @@ select jsonb_strip_nulls('{"a": {"b": null, "c": null}, "d": {} }');
|
||||
{"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
|
||||
----------------------------
|
||||
|
@ -814,6 +814,25 @@ select json_strip_nulls('[1,{"a":1,"b":null,"c":2},3]');
|
||||
-- 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);
|
||||
|
||||
|
@ -1102,6 +1102,24 @@ select jsonb_strip_nulls('[1,{"a":1,"b":null,"c":2},3]');
|
||||
-- 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]');
|
||||
|
Loading…
x
Reference in New Issue
Block a user