PostgreSQL JSON构建没有空值的数组

时间:2018-07-19 22:27:08

标签: arrays json postgresql jsonb

以下查询

SELECT jsonb_build_array(jsonb_build_object('use', 'Home'), 
        CASE WHEN 1 = 2 THEN jsonb_build_object('use', 'Work')
        END)

产生

[{"use":"Home"},null]

我真正想要的时间

[{"use":"Home"}]

我该怎么做? json_strip_nulls()对我不起作用。

4 个答案:

答案 0 :(得分:1)

创建自定义函数似乎是最简单的方法。

create or replace function jsonb_build_array_without_nulls(variadic anyarray)
returns jsonb language sql immutable as $$
    select jsonb_agg(elem)
    from unnest($1) as elem
    where elem is not null
$$;

select 
    jsonb_build_array_without_nulls(
        jsonb_build_object('use', 'home'), 
        case when 1 = 2 then jsonb_build_object('use', 'work') end
    )

 jsonb_build_array_without_nulls 
---------------------------------
 [{"use": "home"}]
(1 row) 

答案 1 :(得分:1)

通过使用像这样的PostgreSQL数组:

SELECT array_to_json(array_remove(ARRAY[jsonb_build_object('use', 'Home'), 
        CASE WHEN 1 = 2 THEN jsonb_build_object('use', 'Work') END], null))

会产生:

[{"use": "Home"}]

同时,请确保:

SELECT array_to_json(array_remove(ARRAY[jsonb_build_object('use', 'Home'), 
        CASE WHEN 1 = 2 THEN jsonb_build_object('use', 'Work') END,
        jsonb_build_object('real_use', 'NotHome')], null))

产生:

[{"use": "Home"},{"real_use": "NotHome"}]

答案 2 :(得分:0)

我假设此查询是通过某种方式动态生成的。如果您控制着SQL的生成,也可以改用ARRAY_AGG(...) FILTER(...),这取决于实际查询,可能比使用所有其他array conversion functions suggested by Patrick更为方便。

SELECT (
  SELECT json_agg(v) FILTER (WHERE v IS NOT NULL)
  FROM (
    VALUES 
      (jsonb_build_object('use', 'Home')),
      (CASE WHEN 1 = 2 THEN jsonb_build_object('use', 'Work') END)
  ) t (v)
)

或者:

SELECT (
  SELECT json_agg(v)
  FROM (
    VALUES 
      (jsonb_build_object('use', 'Home')),
      (CASE WHEN 1 = 2 THEN jsonb_build_object('use', 'Work') END)
  ) t (v)
  WHERE v IS NOT NULL
)

答案 3 :(得分:0)

可以解决此问题的另一种方法是:

SELECT jsonb_build_array(
  jsonb_build_object('use', 'Home'), 
  CASE 
    WHEN 1 = 2 THEN jsonb_build_object('use', 'Work')
    ELSE '"null"'
  END
) - 'null'

(不幸的是,在Postgres或大多数其他数据库中,仅靠null本身并不能做很多事情)

在上述情况下,'"null"'几乎可以替换为不会被误认为数组中实时数据的任何唯一字符串。我不会使用数字,因为- 0实际上会尝试从数组中删除第一项,而不是数组中的数字。但您可能可以使用'"0"',并根据需要使用- '0'之类的内容删除。

对于不使用CASE的用户,可以使用COALESCE将空值转换为所需的字符串(alas,否NVLIFNULLISNULL在postgres中,但至少COALESCE是可移植的)