Is there a json path filtering everything having a specific value?

53 views Asked by At

I'm trying my hands at a, kind of, templating mechanism for JSON.

I have this reduced example JSON template

{
        "type": "AdaptiveCard",
        "body": [
            {
                "type": "Container",
                "isVisible": "$._has_content.success",
                "items": [
                    {
                        "type": "TextBlock",
                        "text": "$.result[0].text",
                    },
                    {
                        "type": "FactSet",
                        "facts": [
                            "$.success.*"
                        ]
                    }
                ]
            },
            {
                "type": "Container",
                "style": "attention",
                "isVisible": "$._has_content.fail",
                "items": [
                    {
                        "type": "TextBlock",
                        "text": "Failures",
                    },
                    {
                        "type": "FactSet",
                        "facts": [
                            "$.fail.*"
                        ]
                    }
                ]
            }
        ],
    }

I now need to filter all those nodes where a value starts with "$".

So these should be found:

        $.body[0].isVisible
        $.body[0].items[0].text
        $.body[0].items[1].facts
        $.body[1].isVisible
        $.body[1].items[1].facts

I just started with JSON Path and have not found a way to define a proper filter.

My attempts like $.body..*[?(@.* =~ /^\$./)] failed.

Update: Additionally to the answer by @gregsdennis, I found, thanks to his reply, the correct syntax I should have used: $..[?(@ =~ /^[$]/)]

1

There are 1 answers

1
gregsdennis On BEST ANSWER

Not all JSON Path implementation support regex, however the official JSON Path spec (just released!) does define match() (implicit anchors) and search() (explicit anchors) regex processing.

Since this is a newly released specification, it's likely not many implementations conform yet. However, mine does, and you can play with it at https://json-everything.net/json-path.

So if you use $.body..*[?search(@, '^\\$.*')], you'll get the results you're looking for:

[
  {
    "Value": "$._has_content.success",
    "Location": "$['body'][0]['isVisible']"
  },
  {
    "Value": "$._has_content.fail",
    "Location": "$['body'][1]['isVisible']"
  },
  {
    "Value": "$.result[0].text",
    "Location": "$['body'][0]['items'][0]['text']"
  },
  {
    "Value": "$.success.*",
    "Location": "$['body'][0]['items'][1]['facts'][0]"
  },
  {
    "Value": "$.fail.*",
    "Location": "$['body'][1]['items'][1]['facts'][0]"
  }
]

which includes the value and location for every node.

Note that the escape \ needs to be doubled because it's in a string literal (JSON escaping rules).

I recommend contacting the implementation maintainers to see what their library supports.