Search code examples
pythonjsonjmespath

JMESPath Path Where Key Might Not Exist


I have a weird JSON construct (I cannot provide the actual data for security reasons, but I can provide the structure, which is all that really matters).

Given the following structure:

[
  {
    "a": {
      "b": {
        "c": "d"
      }
    }
  },
  {
    "b": {
      "c": "d"
    }
  },
]

I need to have a way to always get to c without knowing if the path contains a or not. Something like:

[].*.b.c.d

or

[].a?.b.c.d

Any ideas?

For reference, I am using the jmespath library for python.


Solution

  • Given the JSON:

    [
      {
        "a": {
          "b": {
            "c": "d (of a.b.c)"
          }
        }
      },
      {
        "b": {
          "c": "d (of b.c)"
        }
      },
      {
        "z": {
          "b": {
            "c": "d (of z.b.c)"
          }
        }
      }
    ]
    

    You can use a combination of the or expression (||) and the flatten operator ([]) to achieve what you want.

    So the expression:

    [][*.b || b] [] []
    

    On the above JSON would yield:

    [
      {
        "c": "d (of a.b.c)"
      },
      {
        "c": "d (of b.c)"
      },
      {
        "c": "d (of z.b.c)"
      }
    ]
    

    Note that we have to use the flatten operator twice because of the structure that, sometimes has two levels and sometimes three.


    And if you just want the value of c:

    [][*.b || b] [] [].c
    

    Will yield:

    [
      "d (of a.b.c)",
      "d (of b.c)",
      "d (of z.b.c)"
    ]