Reputation: 13920
JSON-string is SQL-text, JSON-number is SQL-numeric, JSON-boolean is SQL-boolean... So I can do "real good cast"... But:
SELECT to_jsonb('hello'::text)::text
is not good. Returning with quotes. Worst case:
SELECT to_jsonb(1::int)::int;
-- ERROR: cannot cast type jsonb to integer
So, how to do casting?
Upvotes: 1
Views: 4145
Reputation: 13920
((this is a Wiki, you can edit!))
Example using pg 13.5:
SELECT (('{"x":123}'::jsonb)->'x')::int; -- ok no error!
SELECT (('{"x":123.44}'::jsonb)->'x')::float; -- ok no error!
SELECT (('{"x":123.44}'::jsonb)->'x')::numeric; -- ok no error!
SELECT (('{"x":"hello !"}'::jsonb)->'x')::text; -- no error, but quotes
SELECT ('{"x":"hello !"}'::jsonb)->>'x'; -- ok!
-- Modern versions not need cast for simple operations:
SELECT (('{"x":123}'::jsonb)->'x')::int + 3; -- Ok, but...
SELECT jsonb_path_query('{"x":123}', '$.x + 3'); -- How about this!
Today PostgreSQL is not so serious about JSON... So, let's workaround.
Sorry there are questions (mine!) and answers. The answer with the most simple solution is this one:
In pg v9.4.4+ using the
#>>
operator works for me:select to_json('test'::text)#>>'{}';
So, using the question's example:
SELECT (to_json(1::int)#>>'{}')::int; -- the cast works
SELECT (to_jsonB(10.7::numeric)#>>'{}')::numeric; -- internal repres. preserved?
SELECT (to_jsonB(10.7::float)#>>'{}')::float; -- internal repres. preserved?
-- internal JSONb was float or numeric?
SELECT (to_jsonB(true)#>>'{}')::boolean; -- internal representation preserved?
... there are no guarantee that PostgreSQL's internal parser is doing the correct thing, reusing internal numerical representation of JSONb to avoid CPU-time consuption (converting jsonb-number to SQL-text, them casting text to SQL-number).
"JSONb cast optimization" or "SQL datatypes/JSONb datatypes convertion optionmization" seems to still be a big gap for PostgreSQL.
Upvotes: 1
Reputation: 200
Here's a simpler solution that I've found for PostgreSQL.
Assuming:
{
"additionaldata" :
{
"Duration" : "123.44"
}
}
The following select works:
select
(additionaldata -> 'Duration')::jsonb::text::numeric as durationSeconds
from ...
Upvotes: 0