替换 JSON 树中未知位置的 JSON 个对象

Replace JSON objects in unknown positions inside a JSON tree

在 JSON 文件中,我需要使用命令行工具 jq 将加密值替换为明文值作为初始化过程。然后,应用程序将使用自己的密钥重新加密这些值,覆盖明文值。加密值表示为“$crypto”对象,包含有关加密方法和使用的密钥的信息,如下所示:

{
    "$crypto" : {
        "type" : "x-simple-encryption",
        "value" : {
            "cipher" : "AES/CBC/PKCS5Padding",
            "stableId" : "someId",
            "salt" : "4J5ckE6+JaS8TLqAN4073g==",
            "data" : "vBeHAPJXLl+X/8Enp9vxMA==",
            "keySize" : 16,
            "purpose" : "someDescription",
            "iv" : "N2xCe5RiJibHv9hLY+OduA==",
            "mac" : "VoOo1BKptwfqIJeSOb/qGA=="
        }
    }
}

这些“$crypto”对象可以位于 JSON 结构中的任何位置。示例输入文档如下所示:

{
    "unknownKey1" : {
        "unknownKey2" : {
            "name" : "JWT_SESSION",
            "properties" : {
                "maxTokenLifeMinutes" : 120,
                "tokenIdleTimeMinutes" : 30
            }
        },
        "unknownKey3" : [
            {
                "unknownKey4" : "STATIC_USER",
                "unknownKey5" : {
                    "unknownKey6" : "internal/user",
                    "unknownKey7" : "anonymous",
                    "unknownKey8" : {
                        "$crypto" : {
                            "type" : "x-simple-encryption",
                            "value" : {
                                "cipher" : "AES/CBC/PKCS5Padding",
                                "stableId" : "someId",
                                "salt" : "4J5ckE6+JaS8TLqAN4073g==",
                                "data" : "vBeHAPJXLl+X/8Enp9vxMA==",
                                "keySize" : 16,
                                "purpose" : "someDescription",
                                "iv" : "N2xCe5RiJibHv9hLY+OduA==",
                                "mac" : "VoOo1BKptwfqIJeSOb/qGA=="
                            }
                        }
                    }
                },
                "enabled" : true
            }
        ]
    }
}

所以 "unknownKey8" 的值被加密了。我需要该文档如下所示:

{
    "unknownKey1" : {
        "unknownKey2" : {
            "name" : "JWT_SESSION",
            "properties" : {
                "maxTokenLifeMinutes" : 120,
                "tokenIdleTimeMinutes" : 30
            }
        },
        "unknownKey3" : [
            {
                "unknownKey4" : "STATIC_USER",
                "unknownKey5" : {
                    "unknownKey6" : "internal/user",
                    "unknownKey7" : "anonymous",
                    "unknownKey8" : "clearTextValue"
                },
                "enabled" : true
            }
        ]
    }
}

我已经能够使用以下命令在输入文件中找到加密对象:

cat input.json | jq 'paths | select(.[-1] == "$crypto")'
[
  "unknownKey1",
  "unknownKey3",
  0,
  "unknownKey5",
  "unknownKey8",
  "$crypto"
]

但是我无法在执行替换方面取得有意义的进展。

下面进行文中描述的替换。沿

行的调用
jq --arg cleartext "clearTextValue" -f decrypt.jq sample.json

假设。如果您的 jq 没有 walk/1,则要么升级到 jq 1.6,要么在调用之前包含其 def(google 搜索词:jq def walk builtin.jq)。

# input is assumed to be an object
def decrypt($value):
  with_entries(if .value|type == "object"
    then with_entries(if .value | (type == "object" and has("$crypto"))
      then .value = $value else . end)
    else . end) ;

walk(if type == "object" then decrypt($cleartext) else . end)

作为已接受答案的补充,如果使用 jq v1.5,请将其用作 decrypt.jq

# input is assumed to be an object
def decrypt($value):
  with_entries(if .value|type == "object"
    then with_entries(if .value | (type == "object" and has("$crypto"))
      then .value = $value else . end)
    else . end) ;

# walk was added after the release of jq@1.5
def walk(f):
  . as $in
  | if type == "object" then
      reduce keys[] as $key
        ( {}; . + { ($key):  ($in[$key] | walk(f)) } ) | f
  elif type == "array" then map( walk(f) ) | f
  else f
  end;

walk(if type == "object" then decrypt($cleartext) else . end)