The json_strip_nulls function was introduced in 9.5
. What could give an equivalent result for 9.4
?
I have a json
column that is essentially just a text
column, but since the contents are JSON, we made it a json
column for semantic purposes. Now there are a lot of keys mapped to null, and it's wasting space and causing clutter on the screen.
Casting to jsonb
and back doesn't remove the nulls, and 9.4
doesn't give a lot of tools to work with json(b).
1 Answer 1
I think this can be done using an custom aggregate and existing jsonb functionality:
The following aggregate will "merge" two jsonb values into one. Essentially the same as a || b
(where a and b are jsonb values) but as an aggregate for multiple rows.
create aggregate jsonb_merge(jsonb)
(
sfunc = jsonb_concat(jsonb, jsonb),
stype = jsonb
);
With that aggregate it's possible to write a recursive function that removes keys with null values:
create function strip_nulls(p_input jsonb)
returns jsonb
as
$$
select jsonb_aggregate(o)
from (
select jsonb_build_object(t.k, case jsonb_typeof(t.v) when 'object' then strip_nulls(t.v) else t.v end) o
from jsonb_each(p_input) as t(k,v)
where t.v::text <> 'null'
) t;
$$
language sql;
The inner select turns a jsonb value into a set of key/value pairs and removes the null
values recursively. Then the resulting values are aggregated back into a jsonb object.
select strip_nulls('{"one": null,
"two": 2,
"three": {"four": 1, "five": null,
"six": {"seven": 7, "eight": null}
}
}'::jsonb)
returns:
strip_nulls
-----------------------------------------------------
{"two": 2, "three": {"six": {"seven": 7}, "four": 1}}
The result can be cast back to json
I don't have a Postgres 9.4 installation around for testing, but I think I only used functions available in 9.4.
-
Seems like
jsonb_concat
isn't available in9.4
. I suppose the big feature in9.4 was introducing
jsonb` in addition tojson
, and improved tooling only came with9.5
onwards.Kayaman– Kayaman2018年02月07日 13:37:53 +00:00Commented Feb 7, 2018 at 13:37 -
@Kayaman: ah, right. See this question for a function to mimic the
jsonb_concat
in 9.4user1822– user18222018年02月07日 13:43:48 +00:00Commented Feb 7, 2018 at 13:43 -
Thanks! With the old
json_merge
and replacing somejsonb
functions with theirjson
counterparts and casts (jsonb_object_agg
,jsonb_build_object
etc.) I managed to get it working. It doesn't seem to handle arrays, but otherwise seems to work.Kayaman– Kayaman2018年02月07日 14:00:56 +00:00Commented Feb 7, 2018 at 14:00
{"k1": 1, "k2": null, "k3": {"k31": 31, "k32": null}}