【问题标题】:Remove key if the value matches pattern如果值与模式匹配,则删除键
【发布时间】:2021-03-20 23:53:43
【问题描述】:

我有以下 json,如果“值”与特定模式匹配,我想删除键。键的名称不是固定的或预先确定的。

{
    "resources": [{
        "tags": null,
        "properties": {
            "customerId": "1234-cbd9-42bc-9193-f6432a6ef0d4",
            "provisioningState": "Succeeded",
            "sku": {
                "maxCapacityReservationLevel": 3000,
                "lastSkuUpdate": "Fri, 19 Mar 2021 16:38:12 GMT"
            },
            "createdDate": "Fri, 19 Mar 2021 16:38:12 GMT",
            "modifiedDate": "Fri, 19 Mar 2021 17:27:54 GMT",
            "status": {
                "events": [{
                    "count": 1,
                    "firstTimestamp": "2021-03-19T16:40:59Z",
                    "lastTimestamp": "2021-03-19T16:40:59Z",
                    "name": "Pulling",
                    "type": "Normal"
                }]
            }

        }
    }]
}

预期输出

在删除以下键作为值匹配时间戳格式后。

  • lastSkuUpdate
  • 创建日期
  • 修改日期
  • 第一个时间戳
  • 最后一个时间戳
{
    "resources": [{
        "tags": null,
        "properties": {
            "customerId": "1234-cbd9-42bc-9193-f6432a6ef0d4",
            "provisioningState": "Succeeded",
            "sku": {
                "maxCapacityReservationLevel": 3000,
            },
            "status": {
                "events": [{
                    "count": 1,
                    "name": "Pulling",
                    "type": "Normal"
                }]
            }

        }
    }]
}

【问题讨论】:

  • 请展示您尝试过的方法,以及不适合您的方法。
  • 你心目中的时间戳格式是什么?

标签: json jq key-value


【解决方案1】:
"(?x:
   ^
   (?: \\d{4}-\\d{2}-\\d{2}T
   |   \\w{3},[ ][\\d ]\\d[ ]\\w{3}[ ]\\d{4}
   )
)" as $date_pattern |

( .. | select(type == "object") ) |= del(.[
   . as $o |
   keys_unsorted[] |
   select( $o[.] | type == "string" and test($date_pattern) )
])

jqplay

根据自己的喜好调整图案。

【讨论】:

    【解决方案2】:

    从 JSON 对象中删除键值对的直接方法是使用 with_entries,例如像这样:

    def matches:
      type == "string"
      and test("^[1-9]\\d{3}-\\d+-\\d|[1-9]\\d{3} \\d{2}:\\d{2}:\\d{2}");
    
    walk(if type=="object"
         then with_entries(if .value|matches then empty else . end)
         else . end)
    

    您当然可以根据自己的要求调整def matches:,或者将with_entries的filter-argument缩短为:

    select(.value|matches|not)
    

    【讨论】:

      【解决方案3】:

      这是一个表面上复杂但非常有效且实际上非常简单的解决方案。它使用 jq 的流解析器,因此特别适用于非常大的 JSON 输入。当然,此处定义的 matches 过滤器应被视为说明性而非确定性。

      jq --stream -n '
        def matches:
          type == "string"
          and test("^[1-9]\\d{3}-\\d+-\\d|[1-9]\\d{3} \\d{2}:\\d{2}:\\d{2}");
      
        fromstream(inputs
          | select((length==2
                      and (.[0][-1]|type)=="string"
                      and (.[-1]|matches))
                   | not) )
      ' input.json
      
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-12-24
        • 2020-02-18
        • 2019-11-25
        • 2021-11-07
        • 2022-10-15
        • 1970-01-01
        相关资源
        最近更新 更多