78

I have a json type field in postgresql. However I can't select rows where specific field is null:

Code:

SELECT *
FROM   json_array_elements(
  '[{"name": "Toby", "occupation": "Software Engineer"},
    {"name": "Zaphod", "occupation": "Galactic President"} ,
{"name2": "Zaphod", "occupation2": null} ]'  ) AS elem
where elem#>'{occupation2}' is null

This should work but I am getting this error:

ERROR:  operator does not exist: json #> boolean
LINE 6: where elem#>'{occupation2}' is null

5 Answers 5

91

you can use the fact that elem->'occupation2' returns string null of type json, so your query will be:

select
    *
from  json_array_elements(
  '[{"name": "Toby", "occupation": "Software Engineer"},
    {"name": "Zaphod", "occupation": "Galactic President"} ,
    {"name2": "Zaphod", "occupation2": null} ]'
) as elem
where (elem->'occupation2')::text = 'null'

{"name2": "Zaphod", "occupation2": null}

If you want to get all elements where value is null in JSON or key doesn't exists, you can just do:

select
    *
from  json_array_elements(
  '[{"name": "Toby", "occupation": "Software Engineer"},
    {"name": "Zaphod", "occupation": "Galactic President"} ,
    {"name2": "Zaphod", "occupation2": null} ]'
) as elem
where (elem->>'occupation2') is null

{"name": "Toby", "occupation": "Software Engineer"}
{"name": "Zaphod", "occupation": "Galactic President"}
{"name2": "Zaphod", "occupation2": null}
Sign up to request clarification or add additional context in comments.

5 Comments

This worked for me in plpgsql as well. I had to place the json extract in brackets before checking if it is null.
Maybe the associativity rules were obvious to others (and maybe this is what @Imraan was saying as well), but I didn't realize the importance of parentheses before casting to text. Meaning, elem->'occupation2'::text does not work but (as you have), (elem->'occupation2')::text does work.
The second example worked for me. I was missing the parentheses.
Hi @roman, Could you share any postgres documentation stating this behaviour?
Wouldn't this also match "occupation2": "null"? Often the case is that the string "null" is not the same as null.
15

If you are searching for a null value within a json-blob you might want to consider using the function json_typeof(json) that was introduced in Postgres 9.4:

INSERT INTO table
  VALUES ('{ "value": "some", "object": {"int": 1, "nullValue": null}}');

SELECT * FROM table
  WHERE json_typeof(json->'object'->'nullValue') = 'null';

This will result in you finding your entry for the null value.

Hope this helps!

Reference: http://www.postgresql.org/docs/9.4/static/functions-json.html#FUNCTIONS-JSON-PROCESSING-TABLE

Comments

5

For a specific JSON value, cast expression to jsonb and compare it to 'null'::jsonb.

Here, the objective is to find an object that has the key occupation2 and value JSON null. The comparison must not confuse the existence of the key with the value.

Adapting the original:

SELECT *
  FROM json_array_elements(
      '[{"name": "Toby", "occupation": "Software Engineer"},
        {"name": "Zaphod", "occupation": "Galactic President"},
        {"name2": "Zaphod", "occupation2": null}]'
      ) AS elem
    WHERE (elem#>'{occupation2}')::jsonb = 'null'::jsonb
;

1 Comment

This seems like the right answer to avoid catching fields that happen to have the text "null" as a real value.
3

The answers from @roman-pekar and @mraxus were helpful but I was unsatisfied without the ability to clearly distinguish undefined and null... so, I came up with:

CREATE OR REPLACE FUNCTION isnull (element json)
RETURNS boolean AS $$
  SELECT (element IS NOT NULL) AND (element::text = 'null');
$$ LANGUAGE SQL IMMUTABLE STRICT;

select isnull('{"test":null}'::json->'test'); -- returns t
select isnull('{"test":"notnull"}'::json->'test'); -- returns f
select isnull('{"toot":"testundefined"}'::json->'test'); -- returns null

@a_horse_with_no_name also pointed out the additional jsonb operator ? introduced in postgresql version 9.4:

SELECT '{"a":1, "b":2}'::jsonb ? 'b'

1 Comment

To distinguish between null and a non-existing key, you can use the ? operator to test if the key is present.
2

Use dbeaver editor for this, it is working there.

SELECT * FROM json_array_elements('[{"name": "Toby", "occupation": "Software Engineer"},{"name": "Zaphod", "occupation": "Galactic President"},{"name2":"Zaphod","occupation2":null}]') AS elem
where elem#>'{occupation2}') IS 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.