user6127511
user6127511

Reputation: 307

jq - extract additional JSON object into new array

I have some JSON. It looks like this:

{
"Volumes": [
    {
        "Attachments": [
            {
                "VolumeId": "vol-11111111",
                "State": "attached",
                "DeleteOnTermination": false,
                "Device": "/dev/sdz"
            }
        ],
        "Tags": [
            {
                "Value": "volume1",
                "Key": "Name"
            },
            {
                "Value": "00:00",
                "Key": "Start"
            },
            {
                "Value": "00:20",
                "Key": "Finish"
            },
            {
                "Value": "2",
                "Key": "Period"
            }
        ],
        "VolumeId": "vol-11111111"
    },
    {
        "Attachments": [
            {
                "VolumeId": "vol-22222222",
                "State": "attached",
                "DeleteOnTermination": false,
                "Device": "/dev/sdz"
            }
        ],
        "Tags": [
            {
                "Value": "volume2",
                "Key": "Name"
            },
            {
                "Value": "00:00",
                "Key": "Start"
            },
            {
                "Value": "00:20",
                "Key": "Finish"
            },
            {
                "Value": "2",
                "Key": "Period"
            }
        ],
        "VolumeId": "vol-22222222"
    },
    {
        "Attachments": [
            {
                "VolumeId": "vol-333333333",
                "State": "attached",
                "DeleteOnTermination": false,
                "Device": "/dev/sdz"
            }
        ],
        "Tags": [
            {
                "Value": "volume3",
                "Key": "Name"
            },
            {
                "Value": "00:00",
                "Key": "Start"
            },
            {
                "Value": "00:20",
                "Key": "Finish"
            },
            {
                "Value": "2",
                "Key": "Period"
            }
        ],
        "VolumeId": "vol-33333333"
    }
]
}

Using jq, I am able to extract the following information:

VolumeId,Finish,Start,Period

using the jq command

cat json | jq -r '[.Volumes[]|({VolumeId}+(.Tags|from_entries))|{VolumeId,Finish,Start,Period}]'

[
  {
    "VolumeId": "vol-11111111",
    "Finish": "00:20",
    "Start": "00:00",
    "Period": "2"
  },
  {
    "VolumeId": "vol-22222222",
    "Finish": "00:20",
    "Start": "00:00",
    "Period": "2"
  },
  {
    "VolumeId": "vol-33333333",
    "Finish": "00:20",
    "Start": "00:00",
    "Period": "2"
  }
]

All this works fine. However I have the need to additional extract .Attachments.Device. I am looking for output for each array similar to:

 [
  {
    "VolumeId": "vol-11111111",
    "Finish": "00:20",
    "Start": "00:00",
    "Period": "2",
    "DeviceId": "/dev/sdz"
  },
  {
    "VolumeId": "vol-22222222",
    "Finish": "00:20",
    "Start": "00:00",
    "Period": "2",
    "DeviceId": "/dev/sdz"
  },
  {
    "VolumeId": "vol-33333333",
    "Finish": "00:20",
    "Start": "00:00",
    "Period": "2",
    "DeviceId": "/dev/sdz"
  }
]

However I can't figure out how to do this without getting an error. The most logical approach for me would be to do something like:

cat json | jq -r '[.Volumes[]|({VolumeId}+(.Attachments|from_entries)+(.Tags|from_entries))|{VolumeId,Finish,Start,Period,DeviceId}]'

However I get the error:

jq: error (at <stdin>:91): Cannot use null (null) as object key

Any help figuring out what I am not doing correct and how to fix it would be greatly appreciated.

thanks

Upvotes: 3

Views: 1642

Answers (1)

Jeff Mercado
Jeff Mercado

Reputation: 134801

Ultimately, the problem is that you're using from_entries on the Attachments array when it wouldn't work. from_entries takes an array of key/value pair objects to create an object with those values. However, you don't have key/value pairs, but objects. If you're just trying to combine them, you should use add.

Also, there is no property named DeviceId, it's Device. If you want to select the Device property and get it as DeviceId, you need to provide the correct name.

.Volumes | map(
    ({ VolumeId } + (.Attachments | add) + (.Tags | from_entries))
      | { VolumeId, Finish, Start, Period, DeviceId: .Device }
)

Upvotes: 2

Related Questions