如何使用`jq`通过嵌套值过滤此json并打印父键标识符?

时间:2019-08-01 14:52:01

标签: json jq

假设我有这个json

{
  "sha256:0085b5379bf1baeb4a430128782440fe636938aa739f6a5ecc4152a22f19b08b": {
    "imageSizeBytes": "596515805",
    "layerId": "",
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "tag": [
      "python-3-toolchain-0.1.2"
    ],
    "timeCreatedMs": "1564631021992",
    "timeUploadedMs": "1564631067325"
  },
  "sha256:1ec7631f74a3d6d37bf9194c13854f33315260ae1f27347263dd0a8974ee82bb": {
    "imageSizeBytes": "513574770",
    "layerId": "",
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "tag": [
      "python-2-toolchain-latest"
    ],
    "timeCreatedMs": "1535447023647",
    "timeUploadedMs": "1535447042373"
  }
}

我想选择带有特定标签的图像信息(以及sha256摘要)。示例:我只想选择tag == "python-2-toolchain-latest",所以它会打印此json(带有json重新格式化)

 {
    "digest": "sha256:1ec7631f74a3d6d37bf9194c13854f33315260ae1f27347263dd0a8974ee82bb",
    "imageSizeBytes": "513574770",
    "layerId": "",
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "tag": [
      "python-2-toolchain-latest"
    ],
    "timeCreatedMs": "1535447023647",
    "timeUploadedMs": "1535447042373"
  }

我尝试了各种方法,并被困在如何引用sha256关键信息上。

5 个答案:

答案 0 :(得分:1)

可以实现您的目标的jq程序:

# Embed the final result into an array to get a valid JSON output
[
    # Convert the input object into a list of { key, value } objects
    to_entries[]

    # Keep only the objects that contain the desired tag
    # The .tag field may contain multiple tags and the desired one can be at any position
    | select(.value.tag | contains(["python-2-toolchain-latest"]))

    # Add the key into the value object into the .digest property
    | .value.digest = .key

    # Keep only the values (the modified objects)
    | .value

# That's all, folks
]

Try it online!

答案 1 :(得分:0)

这是一个简单明了但有效的解决方案:

keys_unsorted[] as $k
| .[$k] as $value
| select($value.tag[0] ==  "python-2-toolchain-latest")
| {digest: $k} + $value

答案 2 :(得分:0)

这是我的工作。我认为标签数组可以包含多个条目...

.
|to_entries[]
|.key as $k
|.value as $v
|.value.tag[]
|select(.=="python-2-toolchain-latest")
[ { "digest": ($k) }, $v ] | add

看到最高答案后,我更喜欢最后一行:

[ { "digest": ($k) } + $v ]

如果标签可以出现两次,则它将输出相同的记录两次。必须有一个更好的方法来简单地检查tag []数组中是否包含“ python-2-toolchain-latest”。我的jq foo不够强。

答案 3 :(得分:0)

对于那些愿意接受替代方案的人,这是使用基于步行路径的unix实用程序 jtc 可以实现相同的JSON操作:

bash $ <file.json jtc -w'[:]<D>k<tag>l<python-2-toolchain-latest>[-2]' -T'{"digest":{D}",{}}'
{
   "digest": "sha256:1ec7631f74a3d6d37bf9194c13854f33315260ae1f27347263dd0a8974ee82bb",
   "imageSizeBytes": "513574770",
   "layerId": "",
   "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
   "tag": [
      "python-2-toolchain-latest"
   ],
   "timeCreatedMs": "1535447023647",
   "timeUploadedMs": "1535447042373"
}

注意:如果下一个词素中的可搜索上下文唯一标识标签,则不需要词素<tag>l。如果是这样,则可以省略词素

PS>披露:我是jtc-用于JSON操作的shell cli工具的创建者

答案 4 :(得分:0)

我会用

.
| to_entries
| .[]
| select(.value.tag | contains(["python-2-toolchain-latest"]))
| { digest: .key } + .value
  • 我将示例数据放在名为pratama-1.json的文件中。
  • 我运行了以下命令并获得了此输出。
    $ jq '. | to_entries | .[] | select(.value.tag | contains(["python-2-toolchain-latest"])) | { digest: .key } + .value' pratama-1.json
    {
      "digest": "sha256:1ec7631f74a3d6d37bf9194c13854f33315260ae1f27347263dd0a8974ee82bb",
      "imageSizeBytes": "513574770",
      "layerId": "",
      "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
      "tag": [
        "python-2-toolchain-latest"
      ],
      "timeCreatedMs": "1535447023647",
      "timeUploadedMs": "1535447042373"
    }
    

打破这一点

您可以认为jq程序类似于sh管道, 除了: -使用sh(或bash),管道的每个阶段(即,   |之间的每个命令都有一个字节流(通常只是文本),如   它的输入和输出; -使用jq,每个阶段都有一个 JSON流   值作为其输入和输出。

  1. 最简单的jq程序就是.
    • 如果输入为JSON值true,则输出为true
    • 如果输入是JSON值[ true, 3.1416, "foo" ](数组值),则输出是相同的。
    • 如果输入是三个JSON值true3.1416"foo"(布尔值,数字和字符串), 那么三个输出将是该布尔值,该数字和该字符串。
  2. 在脚本的开头,.仅代表输入值,在这种情况下为 您在问题中包含的JSON对象。
  3. 下一阶段是to_entries
    • 它将JSON对象转换为JSON对象的JSON数组。对于像这样的输入:
      {
        "a": 3.1416,
        "b": false
      }
      
      变成这样的数组:
      [
        {
          "key": "a",
          "value": 3.1416
        },
        {
          "key": "b",
          "value": false
        }
      ]
      
  4. 下一阶段是.[],这是一个jq运算符,它将一个JSON值转换为很多:
    • 如果输入是像[ true, 3.1416, "foo" ]这样的单个JSON数组,则三个输出是 JSON值true3.1416"foo"
    • 在我们的例子中,它将所有这些 key-value 对象包装成JSON数组,因此我们可以 输出值,而不是一个JSON数组输出值。
  5. 下一阶段是select(…)
    • 对于每个输入值,它会在括号中计算表达式,然后“传递”该输入 如果表达式为真,则将其作为输出。
    • 例如,对于三个输入true3.1416"foo"select(type == "string") 只有一个输出:字符串"foo"
    • 我的select(…)有两个输入:
      1. JSON对象{ "key": "sha256:008…", "value": { "imageSizeBytes": … } } AND
      2. JSON对象{ "key" :"sha256:1ec…", "value": { "imageSizeBytes": … } }
    • 在我的select(…)内,我使用了一个本身就是jq管道的子表达式:.value.tag | contains(["python-2-toolchain-latest"])
      1. 第一部分.value.tag在每个对象中产生带有键"tag"的字段的值。为您 示例数据,每个值都是一个JSON数组。
      2. 如果输入JSON数组值contains([…])中的所有值,则true部分的值将为[…]的输入JSON数组值 是该输入JSON数组值的成员。
        • 一些例子
        $ jq '. | contains([ "foo" ])' <<< '[ true, 3.1416, "foo" ]'
        true
        $ jq '. | contains([ "foo", true ])' <<< '[ true, 3.1416, "foo" ]'
        true
        $ jq '. | contains([ "foo", true, null ])' <<< '[ true, 3.1416, "foo" ]'
        false
        $ jq '. | contains([ "foo", true, false ])' <<< '[ true, 3.1416, "foo" ]'
        false
        $ jq '. | contains([ "foo", true, null ])' <<< '[ true, 3.1416, "foo" ]'
        false
        
    • 因此,我的select(…)中的表达式对于每个具有 具有JSON子对象值的名为true的密钥,具有JSON数组值的名为"value"的密钥 包含具有JSON字符串值“ python-2-toolchain-latest”的元素。
    • 对于"tag"内的表达式为select(…)的每个输入,该输入值将成为输出值之一。
    • 对于您的示例数据,这只是第二个子对象:true
  6. 管道的最后一步是一个{ "key": "sha256:1ec…", "value": { … } }表达式,它看起来像一个JSON对象。
    • jq说,对于每个输入值,输出具有以下内容的JSON对象值:
      • 名为{ digest: .key }的键 AND
      • 该键的值应该是与名为"digest"的输入JSON对象的键相关联的值。
      • 由于我们的输入是JSON对象"key",因此这将为我们提供输出JSON 对象{ "key": "sha256:1ec…", … }
    • 但是我们也希望在输出JSON对象中包含其他内容:我们想添加与以下内容相关联的JSON对象值 输入对象中的键{ "digest": "sha256:1ec…" }。我们通过添加"value"来实现。
    • + .value jq运算符与JSON对象值一起使用时,会将其操作数JSON对象“合并”为一个输出JSON对象, 例如+产生{ "a": true } + { "b": 3.1416 }
相关问题