使用PostgreSQL处理JSON中的null或缺少属性

时间:2016-01-13 14:24:38

标签: sql json postgresql validation

我正在学习如何在PostgreSQL中处理JSON。

我有一些包含一些列的表。一列是JSON字段。该列中的数据至少包含以下三种变体:

Case 1: {"createDate": 1448067864151, "name": "world"}
Case 2: {"createDate": "", "name": "hello"}
Case 3: {"name": "sky"}

稍后,我想选择createDate。

TO_TIMESTAMP((attributes->>'createDate')::bigint * 0.001)

当数据存在且可转换为bigint时,对于案例1可以正常工作。 但是什么时候不是呢?我该如何处理?

I read this article。它解释了我们可以添加检查约束来执行一些基本验证。或者,我可以在插入数据之前(在客户端)进行模式验证。这两种想法都有利有弊。

使用检查约束

CONSTRAINT validate_createDate CHECK ((attributes->>'createDate')::bigint >= 1)

这会强制一个不可为空的字段(情况3失败)。但我希望该属性是可选的。此外,如果属性没有转换为bigint,因为它是空白的(案例2),则会出错。

在插入

之前在客户端使用JSON模式验证

这部分地起作用,因为模式验证确保了哪些数据符合模式。在我的情况下,我可以控制哪些客户端访问此表,所以这没关系。但是,由于我的验证器将允许通过所有三种情况,因此对SQL不重要。

2 个答案:

答案 0 :(得分:1)

基本上,您需要检查createDate属性是否为空:

WITH data(attributes) AS ( VALUES
  ('{"createDate": 1448067864151, "name": "world"}'::JSON),
  ('{"createDate": "", "name": "hello"}'::JSON),
  ('{"name": "sky"}'::JSON)
)
SELECT to_timestamp((attributes->>'createDate')::bigint * 0.001) FROM data
WHERE
  (attributes->>'createDate') IS NOT NULL
AND
  (attributes->>'createDate') != '';

输出:

        to_timestamp        
----------------------------
 2015-11-20 17:04:24.151-08
(1 row)

答案 1 :(得分:1)

Dmitry's answer上构建,您还可以使用json_typeof函数检查json类型。注意json运算符: - >得到json而不是 - >>始终将值转换为字符串的运算符。

通过使用CASE条件而不是WHERE子句检查SELECT,我们还保留没有createdDate的行。根据您的使用情况,这可能会更好。

WITH data(attributes) AS ( VALUES
  ('{"createDate": 1448067864151, "name": "world"}'::JSON),
  ('{"createDate": "", "name": "hello"}'::JSON),
  ('{"name": "sky"}'::JSON)
)
SELECT
    CASE WHEN (json_typeof(attributes->'createDate') = 'number')
         THEN to_timestamp((attributes->>'createDate')::bigint * 0.001)
    END AS created_date
FROM data
;

输出:

created_date
----------------------------
"2015-11-21 02:04:24.151+01"
""
""
(3 rows)