We are using Postgres 9.3 and making use of the JSON column which was new to that version. Version 9.4 added a LOT of utility functions for handling JSON, as well as the new JSONB column. You can see this by comparing http://www.postgresql.org/docs/9.4/static/functions-json.html with http://www.postgresql.org/docs/9.3/static/functions-json.html
9.4 has a function, json_typeof
which returns the type of a JSON object (as a string: 'string', 'number', 'array', 'object', etc.) I would like to know if there is any practical way in 9.3 of retrieving all rows which are scalars (or, equally useful for us, which are not objects).
We would like the comment
column of a given table to always be a JSON object. This means that we can do queries like:
SELECT comment->>'author' as author_name
FROM our_table
If for some row the JSON in the comment column is an object, but which does not have any such key, you simply get back a NULL.
However, if there is even one scalar in the table, the query fails with the error
ERROR: cannot extract element from a scalar
SQL state: 22023
This is a pain, as we have had strings written to this column some of the time, mainly due to errors. Is there any reasonable way of either filtering these out in a query, or identifying them all so that they can be removed in one go?
Best Answer
Horrible as it is, you could write a PL/PgSQL function that attempts to extract an element from the object, traps the exception if it fails, and returns true on success or false on exception.
Untested:
This'll be pretty inefficient, since it's creating a sub-transaction for each call.
Or you could just update to 9.4.
On 9.4 I can't reproduce your reported error. Trying to look up a key in a json scalar returns null.
... and the same with using
->>
to dereference a scalar.So I'm not sure if this function will work on 9.3, and it won't on 9.4. To be 9.4-compatible you'd have to test if
current_setting('pg_version_num') >= 90400
and return a result based onjson_typeof
instead.You might need to adapt it to use the same expression you use to trigger your reported error.