【问题标题】:Parse JSON values with arbitrary keys使用任意键解析 JSON 值
【发布时间】:2021-10-24 00:01:06
【问题描述】:

我在表中有一个 JSON 字符串列。这些字符串的一部分具有以下格式:

{
    ...
    "rules": {
        "rule_1": {
            "results": [],
            "isTestMode": true
        },
        "rule_2": {
            "results": [],
            "isTestMode": true
        },
        "rule_3": {
            "results": [
                {
                    "required": true,
                    "amount": 99.31
                }
            ],
            "isTestMode": true
        },
        "rule_4": {
            "results": [],
            "isTestMode": false
        },
        ...
    }
    ...
}

在这个嵌套的"rules" 对象中,如果results[0]["required"] = true AND "isTestMode" = false 对于任何规则,我想返回true。问题是"rule_1""rule_2"、..."rule_x" 可以具有事先不知道的任意名称。

是否可以编写一个查询来遍历“规则”中的所有键并检查其中是否有任何一个符合此条件?有没有其他方法可以做到这一点?

如果事先知道密钥,那么我可以这样做:

WHERE 
    (JSON_ARRAY_LENGTH(JSON_EXTRACT(json, '$.rules.rule_1.results')) = 1 
        AND JSON_EXTRACT_SCALAR(json, '$rules.rule_1.results[0].required') = 'true' 
        AND JSON_EXTRACT_SCALAR(json, '$rules.rule_1.isTestMode') = 'false')
    OR (JSON_ARRAY_LENGTH(JSON_EXTRACT(json, '$.rules.rule_2.results')) = 1 
        AND JSON_EXTRACT_SCALAR(json, '$rules.rule_2.results[0].required') = 'true' 
        AND JSON_EXTRACT_SCALAR(json, '$rules.rule_2.isTestMode') = 'false')
    OR ...

【问题讨论】:

  • @ggorlen 这需要在 SQL (Presto) 查询中

标签: sql json presto


【解决方案1】:

您可以提取rules属性并将其转换为MAP(varchar, json)并进行处理:

WITH dataset AS (
    SELECT * FROM (VALUES   
       (JSON '{
    "rules": {
        "rule_1": {
            "results": [],
            "isTestMode": true
        },
        "rule_2": {
            "results": [],
            "isTestMode": true
        },
        "rule_3": {
            "results": [
                {
                    "required": true,
                    "amount": 99.31
                }
            ],
            "isTestMode": true
        },
        "rule_4": {
            "results": [],
            "isTestMode": false
        }
    }
}')
 ) AS t (json_value))

select cardinality(
    filter(
        map_values(cast(json_extract(json_value, '$.rules') as MAP(varchar, json))), -- trasnform into MAP and get it's values
        js -> cast(json_extract(js, '$.isTestMode') as BOOLEAN) -- check isTestMode
            AND cast(json_extract(js, '$.results[0].required') as BOOLEAN)  -- check required of first element of `results`
    )) > 0
from dataset

这将为提供的数据提供true

【讨论】:

    【解决方案2】:

    我能够用正则表达式解决这个问题。不理想,仍然想知道这是否可以使用内置的 JSON 函数来完成。

    WHERE REGEXP_LIKE(json, '.*{"results":\[{"required":true,"amount":\d+.\d+"}],"isTestMode":false}.*')
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-16
      • 2018-12-25
      • 2015-09-13
      相关资源
      最近更新 更多