使用json_build_object动态构建JSON。

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

Dynamically build json with json_build_object

问题

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

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

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

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

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

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

  1. create table json_object (id integer, value1 varchar, qty1 integer, value2 varchar, qty2 integer, value3 varchar, qty3 integer);
  2. insert into json_object values (1, 'A', 10, '', 0, '', 0);
  3. insert into json_object values (2, 'A', 10, 'B', 5, 'C', 10);
  4. insert into json_object values (3, 'A', 10, 'B', 5, '', 0);
  5. select json_build_object(value1, qty1, value2, qty2, value3, qty3) from json_object;

但我希望输出为:

  1. {"A": 10}
  2. {"A": 10, "B": 5, "C": 10}
  3. {"A": 10, "B": 5}
英文:

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

  1. 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:

  1. create table json_object (id integer, value1 varchar, qty1 integer, value2 varchar, qty2 integer, value3 varchar, qty3 integer);
  2. insert into json_object values (1, 'A', 10, '', 0, '', 0);
  3. insert into json_object values (2, 'A', 10, 'B', 5, 'C', 10);
  4. insert into json_object values (3, 'A', 10, 'B', 5, '', 0);
  5. select json_build_object(value1, qty1, value2, qty2, value3, qty3) from json_object;
  6. json_build_object
  7. ----------------------
  8. {"A" : 10, "" : 0, "" : 0}
  9. {"A" : 10, "B" : 5, "C" : 10}
  10. {"A" : 10, "B" : 5, "" : 0}

but I want the output to be:

  1. {"A" : 10}
  2. {"A" : 10, "B" : 5, "C" : 10}
  3. {"A" : 10, "B" : 5}

答案1

得分: 1

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

  1. create table json_object (id integer, value1 varchar, qty1 integer, value2 varchar, qty2 integer, value3 varchar, qty3 integer);
  2. insert into json_object values (1, 'A', 10, '', 0, '', 0);
  3. insert into json_object values (1, 'A', 10, 'B', 5, 'C', 10);
  4. insert into json_object values (1, 'A', 10, 'B', 5, '', 0);
  1. SELECT
  2. CASE
  3. WHEN value1 <> '' AND value2 <> '' AND value3 <> '' THEN
  4. jsonb_build_object(value1, qty1, value2, qty2, value3, qty3)
  5. WHEN value1 <> '' AND value2 <> '' THEN
  6. jsonb_build_object(value1, qty1, value2, qty2)
  7. ELSE
  8. jsonb_build_object(value1, qty1)
  9. END AS json_object
  10. FROM json_object;
  1. create table json_object (id integer, value1 varchar, qty1 integer, value2 varchar, qty2 integer, value3 varchar, qty3 integer);
  2. insert into json_object values (1, 'A', 10, '', 0, '', 0);
  3. insert into json_object values (1, 'A', 10, 'B', 5, 'C', 10);
  4. insert into json_object values (1, 'A', 10, 'B', 5, '', 0);
  1. > status
  2. > CREATE TABLE
  3. > ```
  4. > ``` status
  5. > INSERT 0 1
  6. > ```
  7. > ``` status
  8. > INSERT 0 1
  9. > ```
  10. > ``` status
  11. > INSERT 0 1
  12. > ```

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}
  1. SELECT 3
  1. CREATE OR REPLACE FUNCTION generate_json_object(value1 varchar, qty1 integer, value2 varchar, qty2 integer, value3 varchar, qty3 integer)
  2. RETURNS jsonb AS $$
  3. DECLARE
  4. json_obj jsonb;
  5. BEGIN
  6. json_obj := jsonb_build_object(value1, qty1);
  7. IF value2 <> '' THEN
  8. json_obj := jsonb_set(json_obj, array[value2], to_jsonb(qty2));
  9. END IF;
  10. IF value3 <> '' THEN
  11. json_obj := jsonb_set(json_obj, array[value3], to_jsonb(qty3));
  12. END IF;
  13. RETURN json_obj;
  14. END;
  15. $$ LANGUAGE plpgsql;
  16. SELECT generate_json_object('A', 10, '', 0, '', 0) AS json_object;
  17. SELECT generate_json_object('A', 10, 'B', 5, 'C', 10) AS json_object;
  18. SELECT generate_json_object('A', 10, 'B', 5, '', 0) AS json_object;
  1. CREATE FUNCTION
json_object
{"A": 10}
  1. SELECT 1
json_object
{"A": 10, "B": 5, "C": 10}
  1. SELECT 1
json_object
{"A": 10, "B": 5}

fiddle

英文:
  1. create table json_object (id integer, value1 varchar, qty1 integer, value2 varchar, qty2 integer, value3 varchar, qty3 integer);
  2. insert into json_object values (1, &#39;A&#39;, 10, &#39;&#39;, 0, &#39;&#39;, 0);
  3. insert into json_object values (1, &#39;A&#39;, 10, &#39;B&#39;, 5, &#39;C&#39;, 10);
  4. insert into json_object values (1, &#39;A&#39;, 10, &#39;B&#39;, 5, &#39;&#39;, 0);
  1. SELECT
  2. CASE
  3. WHEN value1 &lt;&gt; &#39;&#39; AND value2 &lt;&gt; &#39;&#39; AND value3 &lt;&gt; &#39;&#39; THEN
  4. jsonb_build_object(value1, qty1, value2, qty2, value3, qty3)
  5. WHEN value1 &lt;&gt; &#39;&#39; AND value2 &lt;&gt; &#39;&#39; THEN
  6. jsonb_build_object(value1, qty1, value2, qty2)
  7. ELSE
  8. jsonb_build_object(value1, qty1)
  9. END AS json_object
  10. FROM json_object;
json_object
{"A": 10}
{"A": 10, "B": 5, "C": 10}
{"A": 10, "B": 5}

fiddle

  1. create table json_object (id integer, value1 varchar, qty1 integer, value2 varchar, qty2 integer, value3 varchar, qty3 integer);
  2. insert into json_object values (1, &#39;A&#39;, 10, &#39;&#39;, 0, &#39;&#39;, 0);
  3. insert into json_object values (1, &#39;A&#39;, 10, &#39;B&#39;, 5, &#39;C&#39;, 10);
  4. 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;

  1. SELECT
  2. CASE
  3. WHEN value1 &lt;&gt; &#39;&#39; AND value2 &lt;&gt; &#39;&#39; AND value3 &lt;&gt; &#39;&#39; THEN
  4. jsonb_build_object(value1, qty1, value2, qty2, value3, qty3)
  5. WHEN value1 &lt;&gt; &#39;&#39; AND value2 &lt;&gt; &#39;&#39; THEN
  6. jsonb_build_object(value1, qty1, value2, qty2)
  7. ELSE
  8. jsonb_build_object(value1, qty1)
  9. END AS json_object
  10. FROM json_object;
json_object
{"A": 10}
{"A": 10, "B": 5, "C": 10}
{"A": 10, "B": 5}
> ``` status
> SELECT 3
> ```
  1. CREATE OR REPLACE FUNCTION generate_json_object(value1 varchar, qty1 integer, value2 varchar, qty2 integer, value3 varchar, qty3 integer)
  2. RETURNS jsonb AS $$
  3. DECLARE
  4. json_obj jsonb;
  5. BEGIN
  6. json_obj := jsonb_build_object(value1, qty1);
  7. IF value2 &lt;&gt; &#39;&#39; THEN
  8. json_obj := jsonb_set(json_obj, array[value2], to_jsonb(qty2));
  9. END IF;
  10. IF value3 &lt;&gt; &#39;&#39; THEN
  11. json_obj := jsonb_set(json_obj, array[value3], to_jsonb(qty3));
  12. END IF;
  13. RETURN json_obj;
  14. END;
  15. $$ LANGUAGE plpgsql;
  16. SELECT generate_json_object(&#39;A&#39;, 10, &#39;&#39;, 0, &#39;&#39;, 0) AS json_object;
  17. SELECT generate_json_object(&#39;A&#39;, 10, &#39;B&#39;, 5, &#39;C&#39;, 10) AS json_object;
  18. 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

以下是翻译好的部分:

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

  1. with transpose as (
  2. select id, to_jsonb(json_object) - 'id' as j
  3. from json_object
  4. ), associate as (
  5. select id, k,
  6. left(k, 1) as ktype,
  7. replace(replace(k, 'qty', ''), 'value', '')::int as knum,
  8. v
  9. from transpose
  10. cross join lateral jsonb_each_text(j) as e(k,v)
  11. )
  12. select jsonb_object_agg(v1.v, v2.v)
  13. from associate v1
  14. join associate v2
  15. on (v1.id, 'q', v1.knum) = (v2.id, v2.ktype, v2.knum)
  16. where v1.ktype = 'v'
  17. and coalesce(v1.v, '') != ''
  18. group by v1.id;

可运行示例

英文:

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

  1. with transpose as (
  2. select id, to_jsonb(json_object) - &#39;id&#39; as j
  3. from json_object
  4. ), associate as (
  5. select id, k,
  6. left(k, 1) as ktype,
  7. replace(replace(k, &#39;qty&#39;, &#39;&#39;), &#39;value&#39;, &#39;&#39;)::int as knum,
  8. v
  9. from transpose
  10. cross join lateral jsonb_each_text(j) as e(k,v)
  11. )
  12. select jsonb_object_agg(v1.v, v2.v)
  13. from associate v1
  14. join associate v2
  15. on (v1.id, &#39;q&#39;, v1.knum) = (v2.id, v2.ktype, v2.knum)
  16. where v1.ktype = &#39;v&#39;
  17. and coalesce(v1.v, &#39;&#39;) != &#39;&#39;
  18. 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:

确定