2

I have rather abstract question on PostgreSQL jsonb data.

For example I have a table called… table_one, where I have a column:

my_jsonb_column   jsonb;

In 100% cases in contains flat json structure like

example:

{"one": null, "two": 0, "three": "" } 

might be different length or null but always flat.

My goal is like that.

Whenever I select this column I need to somehow convert empty string values “” into null for each member of json where it’s value is “”

example :

{"one": null, "two": 0, "three": "" }  - > {"one": null, "two": 0, "three": null } 

Preferable without PLPGsQL

Postgres version - 11

Thank you.

4
  • 1
    maybe too simplistic to just search for "" and replace with null? --> WITH j (val) AS ( VALUES ('{"one": null, "two": 0, "three": "" }'::jsonb)) SELECT replace(val::text,'""','null')::jsonb FROM j Commented Mar 11, 2021 at 18:10
  • 1
    Nice and clean, but unfortunately "" is a valid JSON key and null is not :) Commented Mar 11, 2021 at 18:25
  • 1
    @Stefanov.sm you're right.. I was just considering values, not keys... thanks for pointing out! Commented Mar 11, 2021 at 18:35
  • 1
    @JimJones and "this\"" will bang too :) Commented Mar 11, 2021 at 19:28

3 Answers 3

2

If you want to avoid writing a function, try searching for the empty string "" and using replace to change it to null

WITH j (val) AS (
  VALUES ('{"one": null, "two": 0, "three": "" }'::jsonb)
) SELECT replace(val::text,'""','null')::jsonb FROM j;

                replace                 
----------------------------------------
 {"one": null, "two": 0, "three": null}

Demo: db<>fiddle

If you want the empty strings to be replaced even if you don't say so in your SELECT, you might want to write a TRIGGER on INSERT or UPDATE to keep the jsonb column clean for future selects. Depending on your use case it might be also interesting to take a look at GENERATATED COLUMNS.

Note: as pointed out by @Stefanov.sm, a simple replace wouldn't work if there are keys with empty strings.

Sign up to request clarification or add additional context in comments.

1 Comment

To avoid certain cases (empty string keys, values like "this\"") better use regexp_replace(val::text, '[^\\]("")[^:]?', 'null') instead of replace(val::text,'""','null'). The regexp can be further improved.
1

As a plpgsql function:

create function jsonb_es_to_null(arg_j jsonb) returns jsonb immutable strict as
$body$
 declare retval jsonb := '{}'::jsonb;
 r record;
 begin
    for r in select * from jsonb_each(arg_j) loop
        retval := retval || jsonb_build_object(r.key, case when r.value <> '""' then r.value end);
    end loop;
    return retval;
 end;
$body$ language plpgsql;

Comments

0
select replace('{"one": null, "two": 0, "three": "" }'::jsonb::text, ': ""',': null');

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.