117

Let's say I have a json that looks like this:

some_json = {'key_a': {'nested_key': 'a'},
             'key_b': {'nested_key': 'b'}}

Note that key_a and key_b are optional keys mapped to dictionaries and may or may not exist.

I have a function that checks if an outer key exists in some_json and returns a boolean.

CREATE FUNCTION key_exists(some_json json, outer_key text)
RETURNS boolean AS $$
BEGIN
    RETURN (some_json->outer_key IS NULL);
END;
$$ LANGUAGE plpgsql;

I get the following error:

ProgrammingError: operator does not exist: json -> boolean

Why is outer_key equating to a boolean? What's the proper syntax to perform this check?

0

6 Answers 6

175

You can also use the '?' operator like that:

SELECT '{"key_a":1}'::jsonb ? 'key_a'

And if you need to query by nested key, use like this:

SELECT '{"key_a": {"nested_key": "a"}}'::jsonb -> 'key_a' ? 'nested_key' 

See http://www.postgresql.org/docs/9.5/static/functions-json.html

NOTE: Only for jsonb type.

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

4 Comments

Note when using this in a service that prepares the SQL statements (e.g. Metabase), it won't work, but you might be able to use ?? instead of ?.
This seems like a much better answer, given a key that has a value of null will come back as true, which is expected.
This is the better way, as the top suggestions won't differentiate between a key being set with a NULL value and the key being absent entirely.
No idea what this is actually supposed to return but this didn't work for me and just outputted true for every row when I tried it.
51

Your function does the exact opposite of what the name is, but the way to fix your function is to add ( and ) around the some_json->outer_key.

Here is it fully functioning, and matching the name of your function (notice the NOT in front of the NULL).

CREATE FUNCTION key_exists(some_json json, outer_key text)
RETURNS boolean AS $$
BEGIN
    RETURN (some_json->outer_key) IS NOT NULL;
END;
$$ LANGUAGE plpgsql;

Some tests:

select key_exists('{"key_a": {"nested_key": "a"}, "key_b": {"nested_key": "b"}}'::json, 'key_a');
 key_exists 
------------
 t
(1 row)

And here when a key doesn't exist:

select key_exists('{"key_a": {"nested_key": "a"}, "key_b": {"nested_key": "b"}}'::json, 'test');
 key_exists 
------------
 f
(1 row)

1 Comment

Got it working, thanks! Such a simple fix yet easy to overlook. Also good catch on the name.
11

If you want to select all rows where jsonb key exists you can just use such query:

SELECT * FROM my_table WHERE my_jsonb_field->'my_key' is not null

1 Comment

Make sure to use single quotes!
6

PostgreSQL 14 add subscripting feature for json/jsonb.

SELECT ('{"key_a":1}'::jsonb) ['key_a'] is not null;

return t.

Comments

4

To check key exists or not you can use the operator -> this is used to get Get JSON object field by key For example:

actual json data in column(attribute): {
    "active": "t",
    "email_address": "[email protected]",
    "pin": "2233"
}

SELECT attributes::json->'email_address'
FROM entity
WHERE entity_id = 55;

You can also search key via operator #> and #>>

Get JSON object field as text: '{"a":1,"b":2}'::json->>'b' by using the operator ->>

Comments

3

In Postgres, if you select a key that does not exist it will return null. so u can check the existence of a key by checking the null value of that key.

select '{"key_a": {"nested_key": "a"},
    "key_b": {"nested_key": "b"}}'::jsonb->>'a'
------------
null
(1 row)

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.