Как преобразовать jsonb postgresql 9.4 в объект без языка функции/сервера

Можно ли преобразовать данные jsonb postgresql 9.4 без создания функции и без использования какого-либо языка программирования на стороне сервера?

CREATE TABLE test (id SERIAL PRIMARY KEY,data JSONB);
INSERT INTO test(data) VALUES('{"a":1,"b":2}');
INSERT INTO test(data) VALUES('{"a":3,"b":4,"c":7}');
INSERT INTO test(data) VALUES('{"a":5,"b":5,"d":8}');
SELECT * FROM test;
 id |           data       
----+-------------------------
  1 | {"a": 1, "b": 2}
  2 | {"a": 3, "b": 4, "c": 7}
  3 | {"a": 5, "b": 5, "d": 8}

преобразовать его в:

 {1:[1,2,null,null],2:[3,4,7,null],3:[5,5,null,8]}

person Kokizzu    schedule 28.11.2014    source источник


Ответы (1)


Используйте jsonb_populate_record() (или json_populate_record() вместо json) с хорошо известным типом строки в качестве цели. Вы можете использовать временную таблицу для регистрации типа для специального использования (если вы не можете использовать существующую таблицу или пользовательский составной тип):

CREATE TEMP TABLE obj(a int, b int, c int, d int);

Затем:

SELECT t.id, d.*
FROM   test t
     , jsonb_populate_record(null::obj, t.data) d;

Или используйте jsonb_to_record() (или json_to_record() для json) и укажите список определений столбцов с вызовом:

SELECT t.id, d.*
FROM   test t
     , jsonb_to_record(t.data) d(a int, b int, c int, d int);

Или извлеките и преобразуйте каждое поле по отдельности:

SELECT id, (data->>'a')::int AS a, (data->>'b')::int AS b
         , (data->>'c')::int AS c, (data->>'d')::int AS d
FROM   test;

Все три работают на json и jsonb одинаково. Просто используйте соответствующий вариант функции.

Связанный:

person Erwin Brandstetter    schedule 28.11.2014
comment
@Kokizzu: Это на самом деле новое в 9.4. Две другие опции также находятся на стр. 9.3 (для json). - person Erwin Brandstetter; 28.11.2014
comment
postgre потрясающий XD (я переключаюсь с NoSQL на postgre из-за jsonb) - person Kokizzu; 28.11.2014
comment
@Kokizzu: С возвращением. :) И никогда не называйте это postgre. Это PostgreSQL, Postgres или pg. - person Erwin Brandstetter; 28.11.2014
comment
Для меня это сработало, только если я заменил t.data на t.data::jsonb - person EliadL; 05.11.2019
comment
@EliadL: Как я уже упоминал, для большинства функций JSON существует два варианта. json_to_record() и jsonb_to_record() например. Используйте соответствующий, если это возможно, вместо приведения... - person Erwin Brandstetter; 06.11.2019
comment
@ErwinBrandstetter Я думаю, вы можете упустить мою мысль. Речь идет не о json против jsonb, а о неявном и явном. - person EliadL; 06.11.2019