Search code examples
amazon-web-servicesredisamazon-elasticacheredisjson

Using forward slash (`/`) in key of a RedisJSON object on Amazon Elasticache


We're using AWS Elasticache for Redis with engine 7.1. It has a different behaviour than our tests running on docker image: redis/redis-stack-server:7.2.0-v14.

Best shown through an example:

AWS Elasticache

AWS:6379> del "key"
(integer) 1
AWS:6379> "JSON.SET" "key" "$" "{}" "NX"
OK
AWS:6379> "JSON.SET" "key" "$.path" "{}" "NX"
OK
AWS:6379> json.set "key" "$.path[\"0/1\"]" "{\"ID\":\"0/1\"}"
OK
AWS:6379> json.get "key"
"{\"path\":{\"0\":[null,{\"ID\":\"0/1\"}]}}"

And I can also get:

AWS:6379> json.set "key" "$.path[\"0/1+\"]" "{\"ID\":\"0/1+\"}"
OK
AWS:6379> json.get "key"
"{\"path\":{\"0\":{\"1+\":{\"ID\":\"0/1+\"}}}}"

What happens on tests (docker image: redis/redis-stack-server:7.2.0-v14):

127.0.0.1:49960> del "key"
(integer) 0
127.0.0.1:49960> "JSON.SET" "key" "$" "{}" "NX"
OK
127.0.0.1:49960> "JSON.SET" "key" "$.path" "{}" "NX"
OK
127.0.0.1:49960> json.set "key" "$.path[\"0/1\"]" "{\"ID\":\"0/1+\"}"
OK
127.0.0.1:49960> json.get "key"
"{\"path\":{\"0/1\":{\"ID\":\"0/1+\"}}}"

So what I expect to happen is the JSON path is analysed as is, and "0/1" is used as the key, just like in our tests. I tried multiple options for path "0\/1", "0\\/1", "0\\\/1", but none give the wanted result.


Solution

  • You could achieve what you're trying to do by defining your JSON in the json parameter rather than the path parameter as following

    > json.set "key" . '{"path":{"0/1":{"ID":"0/1+"}}}'
    OK
    > json.get "key"
    "{\"path\":{\"0/1\":{\"ID\":\"0/1+\"}}}"
    

    And still able to access your key

    > json.get "key" $.path.0/1.ID
    "[\"0/1+\"]"
    

    Not sure if you absolutely need to use the path parameter to define your JSON, but if you do there's probably an issue on how AWS is handling the escaping of forward slash with the json.set command...

    Edit:

    You need to use ~1 instead of / like following:

    > json.set "key" "$" "{}" "NX"
    OK
    > json.set "key" "$.path" "{}" "NX"
    OK
    > json.set "key" "$.path[\"0~11\"]" "{\"ID\":\"0/1+\"}"
    OK
    > json.get "key"
    "{\"path\":{\"0/1\":{\"ID\":\"0/1+\"}}}"
    

    Links:

    Because the characters '~' (%x7E) and '/' (%x2F) have special
    meanings in JSON Pointer, '~' needs to be encoded as '~0' and '/'
    needs to be encoded as '~1' when these characters appear in a
    reference token.