如何使用JQ将JSON中的间歇性字符串元素转换为数组

时间:2019-05-08 02:35:37

标签: json jq

我有一个带有Statement.Action元素的IAM策略,Statement.Action元素既是数组又是字符串,具体取决于它们中的条目数。

例如,有一些诸如

    {
        "Sid": "Name1",
        "Effect": "Allow",
        "Action": [
            "logs:GetLogEvents",
            "ecs:DeleteCluster",
            "logs:PutRetentionPolicy",
            "logs:PutLogEvents",
            "s3:GetReplicationConfiguration"
        ],
       "Resource": "arn:aws:cognito-idp:*:*:userpool/*",
        "Condition": {
            "ForAllValues:StringEquals": {
                "aws:ResourceTag/VendorType": "ABC"
            }
        }
    },

,还有Statement.Action元素,例如

    {
        "Sid": "Name2",
        "Effect": "Allow",
        "Action": "cognito-identity:DeleteIdentityPool",
        "Resource": "arn:aws:cognito-identity:*:*:identitypool/*",
        "Condition": {
            "ForAllValues:StringEquals": {
                "aws:ResourceTag/VendorType": "ABC"
            }
        }
    },

基本上,我希望能够对“动作”下的元素进行排序。

但是,由于运行以下命令时某些操作项是字符串而不是数组

jq '.Statement[].Action|=(. // [] | sort)' file.json 

我收到错误

jq: error (at file.json:277): string ("cognito-id...) cannot be sorted, as it is not an array

如果所有Statement []。Action元素都位于数组中而某些不是字符串,则可以解决此问题。

因此,如果我将json中的上述错误条目更改为以下内容,则可以解决该问题。

    {
        "Sid": "Name2",
        "Effect": "Allow",
        "Action": [
            "cognito-identity:DeleteIdentityPool"
        ],
        "Resource": "arn:aws:cognito-identity:*:*:identitypool/*",
        "Condition": {
            "ForAllValues:StringEquals": {
                "aws:ResourceTag/VendorType": "ABC"
            }
        }
    },

我可以使用jq命令的什么组合来获得其中Statement []。Action是字符串而不是将数组转换为上述数组的项,因此我可以对其中的元素进行排序。

感谢您的帮助

1 个答案:

答案 0 :(得分:1)

我们假设带有“ Action”键的对象在数组中。然后,您可以通过编写以下内容来对作为数组的“动作”值进行排序:

map( .Action |= (if type=="array" then sort else . end) )

或者,如果您想确保.Action始终是数组值:

map( .Action |= (if type=="array" then sort else [.] end) )

。声明

因此,您可能想要编写如下内容:

jq '.Statement[].Action |= (if type == "array" then sort else . end)' file.json