skip to Main Content

I have an object that looks like this

{
  "my_list": [
    {
      "name": "an_image",
      "image": "an_image.com"
    },
    {
      "name": "another_image",
      "image": "another_image.com"
    },
  ...<more objects with image property>
  ],
  "foo": {
    "image": "foobar.io"
  },
  "bar": {
    "image": "bar_image.io"
  },
  ...<more objects with image property>
}

I’d like to get all of the image properties from each of the objects, and from each object in my_list and other lists that have objects that include an image property. So in this example I’d like to get

"an_image.com"
"another_image.com"
"foobar.io"
"bar_image.io"

We don’t know the keys of any of these objects at runtime, so we can’t reference my_list, foo, or bar in this example.

Previously we didn’t have my_list in the object and jq '.[].image' worked, but now that results in jq: error (at bar.json:18): Cannot index array with string "image".

The problem is that we don’t know the name of the objects that contain image properties so we can’t reference them explicitly, and now that we’ve added another element that’s a list we’re running into type errors, that I’m not sure how to solve.

I’ve tried various combinations of .[].image, but they all seem to run into issues with typing.

4

Answers


  1. If you don’t mind the terseness, you could perhaps go with:

    jq '..|select(.image?).image'
    
    Login or Signup to reply.
  2. You could select by objects and items of arrays:

    jq '.[] | ., arrays[] | objects.image'
    
    "an_image.com"
    "another_image.com"
    "foobar.io"
    "bar_image.io"
    

    Demo

    Login or Signup to reply.
  3. Using recursive descent .. is more elegant:

    jq '.. | .image? // empty'
    
    Login or Signup to reply.
  4. If the input is large, you might want to consider streaming the data in:

    $ jq --stream -r 'select(.[0][-1] == "image")[1] // empty' input.json
    an_image.com
    another_image.com
    foobar.io
    bar_image.io
    

    When streamed, your input will be processed as path/value pairs for the most part. Filter the paths you want, then return the value.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search