Search code examples
postgresqljsonbhstore

Construct JSONB from separate arrays of keys and values


PostgreSQL has a very useful hstore(text[], text[]) function which will "construct an hstore from separate key and value arrays". I am looking for a JSONB equivalent, but there isn't one that I can see. Maybe I will need to rewrite my statement instead, which I am looking into (but could use some help, as I can't think of a way to "merge" the two arrays)

SELECT HSTORE(ARRAY['value1', 'value2', 'value3'], 
  (SELECT ARRAY_AGG(ROUND(n, 3)) FROM UNNEST(ARRAY[1.001, 2.0045, 3]) n)::TEXT[]);

As you can see, the first parameter is "keys" and the second parameter is "values", but rounded down to three digits. Instead of an HSTORE object, I want JSONB in the end.

Please don't suggest casting from HSTORE to JSONB, I want to get rid of the HSTORE extension too ;) But yeah, that would work otherwise.

I'm using PostgreSQL 11.4.

NOTE: The function jsonb_object(keys text[], values text[]) is awfully close to what I need, except values are restricted to TEXT[] and I need NUMERIC[].


ANSWER (adapted from a_horse_with_no_name's answer)

SELECT jsonb_object_agg(key, val)
FROM (
  SELECT key, ROUND(val, 3) as val 
  FROM UNNEST(ARRAY['value1', 'value2', 'value3'], ARRAY[1.001, 2.0045, 3]) AS row(key, val)
) t;

Solution

  • If you are certain that both arrays always have the same number of elements, you can use something like this:

    select jsonb_object_agg(k,v)
    from (
      select unnest(ARRAY['value1', 'value2', 'value3']) as k, 
             unnest(ARRAY[1.001, 2.0045, 3]) as v
    ) t;
    

    If you need that often, I would create a function for that:

    create function jsonb_from_array(p_keys text[], p_values anyarray)
      returns jsonb
    as
    $$
      select jsonb_object_agg(k,v)
      from (
        select unnest(p_keys) as k, 
               unnest(p_values) as v
      ) t;
    $$
    language sql
    immutable;