如何防止在 PostgreSQL 的 JSON 列中插入“”或 [](空字符串)作为值

How to prevent inserting "" or [] (empty string) as value in JSON column in PostgreSQL

我想防止在 json 列中插入“”或 [](空 strings/array)。请考虑以下示例:-

{"city":"LONDON","country":"UK","addressLine1":"PO Box 223456","postCode":"","addressLine2":"PO Box 47854"}

那么输出应该删除 "postcode":"" 并且应该如下所示:-

{"city":"LONDON","country":"UK","addressLine1":"PO Box 223456","addressLine2":"PO Box 47854"}

谁能帮我解决这个问题?

您可以像这样删除这些空值:

with my_table(json_col) as (
values (
'{
    "city": "LONDON",
    "country": "UK",
    "addressLine1": "PO Box 223456",
    "postCode": "",
    "addressLine2": "PO Box 47854",
    "array_to_delete": []
}'::jsonb)
)

select jsonb_object_agg(key, value)
from my_table
cross join lateral jsonb_each(json_col)
where value not in ('""', '[]');

                                           jsonb_object_agg                                           
------------------------------------------------------------------------------------------------------
 {"city": "LONDON", "country": "UK", "addressLine1": "PO Box 223456", "addressLine2": "PO Box 47854"}
(1 row) 

更新。在 Postgres 9.3 中:

with my_table(json_col) as (
values (
'{
    "city": "LONDON",
    "country": "UK",
    "addressLine1": "PO Box 223456",
    "postCode": "",
    "addressLine2": "PO Box 47854",
    "array_to_delete": []
}'::json)
)

select format('{%s}',string_agg(format('"%s": %s', key, to_json(value)), ','))::json
from my_table
cross join lateral json_each_text(json_col)
where value not in ('', '[]');

                                              format                                               
---------------------------------------------------------------------------------------------------
 {"city": "LONDON","country": "UK","addressLine1": "PO Box 223456","addressLine2": "PO Box 47854"}
(1 row)

更新。在这种情况下,无法应用检查约束,因为它只能接受或拒绝输入数据,而您要修改它。您可以使用上述算法创建一个函数并在触发器中使用它:

create or replace function filter_json_input()
returns trigger language plpgsql as $$
begin
    select format('{%s}', string_agg(format('"%s": %s', key, to_json(value)), ','))::json
    from json_each_text(new.json_col)
    where value not in ('', '[]')
    into new.json_col;
    return new;
end $$;

Full example in rextester.

使用 CTE 您可以通过以下查询来完成:

WITH j AS(
SELECT *
FROM json_each_text('{"city":"LONDON","country":"UK","addressLine1":"PO Box 223456","postCode":"","addressLine2":"PO Box 47854"}'::json)
WHERE value <> ''
) SELECT json_object_agg(j.key,j.value) FROM j

我也用PG 9.3。这是一个解决方案......也许太hacky了?但它有效,我们经常手动构建 JSON 对象,因为它更快:P

SELECT ('{' || STRING_AGG('"' || key || '":' || TO_JSON(value), ',') || '}')::JSON
FROM json_each_text('{"city":"LONDON","country":"UK","addressLine1":"PO Box 223456","postCode":"","addressLine2":"PO Box 47854"}'::JSON)
WHERE COALESCE(value, '') <> ''

结果:{"city":"LONDON","country":"UK","addressLine1":"PO Box 223456","addressLine2":"PO Box 47854"}