使用json_build_object动态构建JSON。

huangapple go评论78阅读模式
英文:

Dynamically build json with json_build_object

问题

我使用 json_build_object 来构建一个 JSON 对象,使用其他列:

json_build_object(value1, qty1, value2, qty2, value3, qty3)

每一对 (value, qty) 一起使用。

我只想让 JSON 对象包含不为空的值对。

目前,在 json_build_object 中的每一对都是硬编码的。我该如何更改?

到目前为止,我有以下内容:

create table json_object (id integer, value1 varchar, qty1 integer, value2 varchar,  qty2 integer, value3 varchar,  qty3 integer);

insert into json_object values (1, 'A', 10, '', 0, '', 0);
insert into json_object values (2, 'A', 10, 'B', 5, 'C', 10);
insert into json_object values (3, 'A', 10, 'B', 5, '', 0);

select json_build_object(value1, qty1, value2, qty2, value3, qty3) from json_object;

但我希望输出为:

{"A": 10}
{"A": 10, "B": 5, "C": 10}
{"A": 10, "B": 5}
英文:

I am using json_build_object to build a json object using other columns:

json_build_object(value1, qty1, value2, qty2, value3, qty3)

Every pair (value, qty) go together.

I only want the json object to contain the pairs that don't have an empty value.

At the moment, each pair in json_build_object is hardcoded. How can I change that?

I have this so far:

create table json_object (id integer, value1 varchar, qty1 integer, value2 varchar,  qty2 integer, value3 varchar,  qty3 integer);

insert into json_object values (1, 'A', 10, '', 0, '', 0);
insert into json_object values (2, 'A', 10, 'B', 5, 'C', 10);
insert into json_object values (3, 'A', 10, 'B', 5, '', 0);

select json_build_object(value1, qty1, value2, qty2, value3, qty3) from json_object;

 json_build_object   
----------------------
{"A" : 10, "" : 0, "" : 0}
{"A" : 10, "B" : 5, "C" : 10}
{"A" : 10, "B" : 5, "" : 0}

but I want the output to be:

{"A" : 10}
{"A" : 10, "B" : 5, "C" : 10}
{"A" : 10, "B" : 5}

答案1

得分: 1

以下是您要求的翻译部分:

create table json_object (id integer, value1 varchar, qty1 integer, value2 varchar,  qty2 integer, value3 varchar,  qty3 integer);

insert into json_object values (1, 'A', 10, '', 0, '', 0);
insert into json_object values (1, 'A', 10, 'B', 5, 'C', 10);
insert into json_object values (1, 'A', 10, 'B', 5, '', 0);
SELECT 
  CASE 
    WHEN value1 <> '' AND value2 <> '' AND value3 <> '' THEN 
      jsonb_build_object(value1, qty1, value2, qty2, value3, qty3)
    WHEN value1 <> '' AND value2 <> '' THEN 
      jsonb_build_object(value1, qty1, value2, qty2)
    ELSE 
      jsonb_build_object(value1, qty1)
  END AS json_object
FROM json_object;
create table json_object (id integer, value1 varchar, qty1 integer, value2 varchar,  qty2 integer, value3 varchar,  qty3 integer);

insert into json_object values (1, 'A', 10, '', 0, '', 0);
insert into json_object values (1, 'A', 10, 'B', 5, 'C', 10);
insert into json_object values (1, 'A', 10, 'B', 5, '', 0);
> status
> CREATE TABLE
> ```

> ``` status
> INSERT 0 1
> ```

> ``` status
> INSERT 0 1
> ```

> ``` status
> INSERT 0 1
> ```

SELECT
CASE
WHEN value1 <> '' AND value2 <> '' AND value3 <> '' THEN
jsonb_build_object(value1, qty1, value2, qty2, value3, qty3)
WHEN value1 <> '' AND value2 <> '' THEN
jsonb_build_object(value1, qty1, value2, qty2)
ELSE
jsonb_build_object(value1, qty1)
END AS json_object
FROM json_object;


json_object
{"A": 10}
{"A": 10, "B": 5, "C": 10}
{"A": 10, "B": 5}
SELECT 3
CREATE OR REPLACE FUNCTION generate_json_object(value1 varchar, qty1 integer, value2 varchar, qty2 integer, value3 varchar, qty3 integer)
RETURNS jsonb AS $$
DECLARE
  json_obj jsonb;
BEGIN
  json_obj := jsonb_build_object(value1, qty1);
  
  IF value2 <> '' THEN
    json_obj := jsonb_set(json_obj, array[value2], to_jsonb(qty2));
  END IF;
  
  IF value3 <> '' THEN
    json_obj := jsonb_set(json_obj, array[value3], to_jsonb(qty3));
  END IF;
  
  RETURN json_obj;
END;
$$ LANGUAGE plpgsql;

SELECT generate_json_object('A', 10, '', 0, '', 0) AS json_object;
SELECT generate_json_object('A', 10, 'B', 5, 'C', 10) AS json_object;
SELECT generate_json_object('A', 10, 'B', 5, '', 0) AS json_object;
CREATE FUNCTION
json_object
{"A": 10}
SELECT 1
json_object
{"A": 10, "B": 5, "C": 10}
SELECT 1
json_object
{"A": 10, "B": 5}

fiddle

英文:
create table json_object (id integer, value1 varchar, qty1 integer, value2 varchar,  qty2 integer, value3 varchar,  qty3 integer);

insert into json_object values (1, &#39;A&#39;, 10, &#39;&#39;, 0, &#39;&#39;, 0);
insert into json_object values (1, &#39;A&#39;, 10, &#39;B&#39;, 5, &#39;C&#39;, 10);
insert into json_object values (1, &#39;A&#39;, 10, &#39;B&#39;, 5, &#39;&#39;, 0);

SELECT 
  CASE 
    WHEN value1 &lt;&gt; &#39;&#39; AND value2 &lt;&gt; &#39;&#39; AND value3 &lt;&gt; &#39;&#39; THEN 
      jsonb_build_object(value1, qty1, value2, qty2, value3, qty3)
    WHEN value1 &lt;&gt; &#39;&#39; AND value2 &lt;&gt; &#39;&#39; THEN 
      jsonb_build_object(value1, qty1, value2, qty2)
    ELSE 
      jsonb_build_object(value1, qty1)
  END AS json_object
FROM json_object;

json_object
{"A": 10}
{"A": 10, "B": 5, "C": 10}
{"A": 10, "B": 5}

fiddle

create table json_object (id integer, value1 varchar, qty1 integer, value2 varchar,  qty2 integer, value3 varchar,  qty3 integer);

insert into json_object values (1, &#39;A&#39;, 10, &#39;&#39;, 0, &#39;&#39;, 0);
insert into json_object values (1, &#39;A&#39;, 10, &#39;B&#39;, 5, &#39;C&#39;, 10);
insert into json_object values (1, &#39;A&#39;, 10, &#39;B&#39;, 5, &#39;&#39;, 0);

> status
&gt; CREATE TABLE
&gt;

> status
&gt; INSERT 0 1
&gt;

> status
&gt; INSERT 0 1
&gt;

> status
&gt; INSERT 0 1
&gt;

SELECT 
  CASE 
    WHEN value1 &lt;&gt; &#39;&#39; AND value2 &lt;&gt; &#39;&#39; AND value3 &lt;&gt; &#39;&#39; THEN 
      jsonb_build_object(value1, qty1, value2, qty2, value3, qty3)
    WHEN value1 &lt;&gt; &#39;&#39; AND value2 &lt;&gt; &#39;&#39; THEN 
      jsonb_build_object(value1, qty1, value2, qty2)
    ELSE 
      jsonb_build_object(value1, qty1)
  END AS json_object
FROM json_object;

json_object
{"A": 10}
{"A": 10, "B": 5, "C": 10}
{"A": 10, "B": 5}
> ``` status
> SELECT 3
> ```
CREATE OR REPLACE FUNCTION generate_json_object(value1 varchar, qty1 integer, value2 varchar, qty2 integer, value3 varchar, qty3 integer)
RETURNS jsonb AS $$
DECLARE
  json_obj jsonb;
BEGIN
  json_obj := jsonb_build_object(value1, qty1);
  
  IF value2 &lt;&gt; &#39;&#39; THEN
    json_obj := jsonb_set(json_obj, array[value2], to_jsonb(qty2));
  END IF;
  
  IF value3 &lt;&gt; &#39;&#39; THEN
    json_obj := jsonb_set(json_obj, array[value3], to_jsonb(qty3));
  END IF;
  
  RETURN json_obj;
END;
$$ LANGUAGE plpgsql;

SELECT generate_json_object(&#39;A&#39;, 10, &#39;&#39;, 0, &#39;&#39;, 0) AS json_object;
SELECT generate_json_object(&#39;A&#39;, 10, &#39;B&#39;, 5, &#39;C&#39;, 10) AS json_object;
SELECT generate_json_object(&#39;A&#39;, 10, &#39;B&#39;, 5, &#39;&#39;, 0) AS json_object;

> status
&gt; CREATE FUNCTION
&gt;

json_object
{"A": 10}
> ``` status
> SELECT 1
> ```
json_object
{"A": 10, "B": 5, "C": 10}
> ``` status
> SELECT 1
> ```
json_object
{"A": 10, "B": 5}
> ``` status
> SELECT 1
> ```

fiddle

答案2

得分: 1

以下是翻译好的部分:

这将有效,只要列名遵循常规约定:

with transpose as (
  select id, to_jsonb(json_object) - 'id' as j
    from json_object
), associate as (
  select id, k, 
         left(k, 1) as ktype,
         replace(replace(k, 'qty', ''), 'value', '')::int as knum,
         v
    from transpose
         cross join lateral jsonb_each_text(j) as e(k,v)
)
select jsonb_object_agg(v1.v, v2.v)
  from associate v1
       join associate v2 
         on (v1.id, 'q', v1.knum) = (v2.id, v2.ktype, v2.knum)
 where v1.ktype = 'v'
   and coalesce(v1.v, '') != '' 
 group by v1.id;

可运行示例

英文:

This will work so long as the column names follow a regular convention:

with transpose as (
  select id, to_jsonb(json_object) - &#39;id&#39; as j
    from json_object
), associate as (
  select id, k, 
         left(k, 1) as ktype,
         replace(replace(k, &#39;qty&#39;, &#39;&#39;), &#39;value&#39;, &#39;&#39;)::int as knum,
         v
    from transpose
         cross join lateral jsonb_each_text(j) as e(k,v)
)
select jsonb_object_agg(v1.v, v2.v)
  from associate v1
       join associate v2 
         on (v1.id, &#39;q&#39;, v1.knum) = (v2.id, v2.ktype, v2.knum)
 where v1.ktype = &#39;v&#39;
   and coalesce(v1.v, &#39;&#39;) != &#39;&#39; 
 group by v1.id;

Working fiddle

huangapple
  • 本文由 发表于 2023年7月23日 21:09:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/76748411.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定