How can I write a JMESPath expression to select a keys containing brackets ("({")?

49 views Asked by At

Given the dictionary

product_data = {
    'restrictions({"basketItems":[],"endDateTime":"","startDateTime":""})': [
        {
            '__typename': 'ProductRestrictionType',
            'type': 'RdgDateRange',
            'isViolated': False,
            'message': 'Price Cuts - Was £0.50\n'
        }, {
            '__typename': 'ProductRestrictionType',
            'type': 'ExcludedProduct',
            'isViolated': True,
            'message': 'This product is unavailable'
        }
    ]
}

I wanted to select the following key

restrictions({"basketItems":[],"endDateTime":"","startDateTime":""})

I tried the following but I am getting an error due to brackets:

import jmespath

expression = jmespath.compile('restrictions({"basketItems":],"endDateTime":"","startDateTime":""})')
result = expression.search(product_data)

How can I fix this expression JMESPath?

1

There are 1 answers

0
β.εηοιτ.βε On

As pointed in the specifications:

An identifier can also be quoted. This is necessary when an identifier has characters not specified in the unquoted-string grammar rule. In this situation, an identifier is specified with a double quote, followed by any number of unescaped-char or escaped-char characters, followed by a double quote.

Source: https://jmespath.org/specification.html#identifiers

And given that unquoted-string is A-Za-z0-9_.

In order to select a key in a JSON like

{
  "foo({})": "bar"
}

You would use the expression:

"foo({})"

Yielding:

"bar"

But since you also have quotes in the string, you would have to escape those quotes, e.g.:

{
  "foo({\"\"})": "def"
}

Would be queried with:

"foo({\"\"})"

And finally, since you are in a Python string, in order for the escaping character, backslash, to be a literal \ and not an escaping sequence, you'll have to double it:

expression = jmespath.compile(
    '"restrictions({\\"basketItems\\":[],\\"endDateTime\\":\\"\\"'
    + ',\\"startDateTime\\":\\"\\"})"'
)

Full code, with an expression string split for readability:

import jmespath
from pprint import pprint

product_data = {
    'restrictions({"basketItems":[],"endDateTime":"","startDateTime":""})': [
        {
            '__typename': 'ProductRestrictionType',
            'type': 'RdgDateRange',
            'isViolated': False,
            'message': 'Price Cuts - Was £0.50\n'
        }, {
            '__typename': 'ProductRestrictionType',
            'type': 'ExcludedProduct',
            'isViolated': True,
            'message': 'This product is unavailable'
        }
    ]
}

expression = jmespath.compile(
    '"restrictions({\\"basketItems\\":[],\\"endDateTime\\":\\"\\"'
    + ',\\"startDateTime\\":\\"\\"})"'
)
result = expression.search(product_data)
pprint(result)

Would yield:

[{'__typename': 'ProductRestrictionType',
  'isViolated': False,
  'message': 'Price Cuts - Was £0.50\n',
  'type': 'RdgDateRange'},
 {'__typename': 'ProductRestrictionType',
  'isViolated': True,
  'message': 'This product is unavailable',
  'type': 'ExcludedProduct'}]