From 130cf4e874c2caf03eefa26a77b7a4e80539a942 Mon Sep 17 00:00:00 2001 From: shacharPash Date: Sun, 14 May 2023 16:39:52 +0300 Subject: support JSON.MERGE Command --- redis/commands/json/__init__.py | 1 + redis/commands/json/commands.py | 22 ++++++++++++++++++++++ tests/test_json.py | 16 ++++++++++++++++ 3 files changed, 39 insertions(+) diff --git a/redis/commands/json/__init__.py b/redis/commands/json/__init__.py index 7d55023..77fb21c 100644 --- a/redis/commands/json/__init__.py +++ b/redis/commands/json/__init__.py @@ -38,6 +38,7 @@ class JSON(JSONCommands): "JSON.GET": self._decode, "JSON.MGET": bulk_of_jsons(self._decode), "JSON.SET": lambda r: r and nativestr(r) == "OK", + "JSON.MERGE": lambda r: r and nativestr(r) == "OK", "JSON.NUMINCRBY": self._decode, "JSON.NUMMULTBY": self._decode, "JSON.TOGGLE": self._decode, diff --git a/redis/commands/json/commands.py b/redis/commands/json/commands.py index c02c47a..5da9245 100644 --- a/redis/commands/json/commands.py +++ b/redis/commands/json/commands.py @@ -253,6 +253,28 @@ class JSONCommands: pieces.append("XX") return self.execute_command("JSON.SET", *pieces) + def merge( + self, + name: str, + path: str, + obj: JsonType, + decode_keys: Optional[bool] = False, + ) -> Optional[str]: + """ + Sets or updates the JSON value at a path.. + + ``decode_keys`` If set to True, the keys of ``obj`` will be decoded + with utf-8. + + For more information see `JSON.MERGE `_. + """ + if decode_keys: + obj = decode_dict_keys(obj) + + pieces = [name, str(path), self._encode(obj)] + + return self.execute_command("JSON.MERGE", *pieces) + def set_file( self, name: str, diff --git a/tests/test_json.py b/tests/test_json.py index 8e8da05..9d85c1e 100644 --- a/tests/test_json.py +++ b/tests/test_json.py @@ -47,6 +47,22 @@ def test_json_get_jset(client): assert client.exists("foo") == 0 +@pytest.mark.redismod +@skip_ifmodversion_lt("99.99.99", "ReJSON") # todo: update after the release +def test_json_merge(client): + assert client.json().set("test_merge", Path.root_path(), '{"person":{"name":"John Doe","age":25,"address":{"home":"123 Main Street"},"phone":"123-456-7890"}}') + assert client.json().merge("test_merge", Path.root_path(), '{"person":{"age":30}}') + assert client.json().get("test_merge") == '{"person":{"name":"John Doe","age":30,"address":{"home":"123 Main Street"},"phone":"123-456-7890"}}' + + # Test with root path path $.a.b + assert client.json().merge("test_merge", Path("person", "address"), '{"work":"Redis office"}') + assert client.json().get("test_merge") == '{"person":{"name":"John Doe","age":30,"address":{"home":"123 Main Street","work":"Redis office"},"phone":"123-456-7890"}}' + + # Test with null value to delete a value + assert client.json().merge("test_merge", Path("person", "address"), '{"work":null}') + assert client.json().get("test_merge") == '{"person":{"name":"John Doe","age":30,"address":{"home":"123 Main Street"},"phone":"123-456-7890"}}' + + @pytest.mark.redismod def test_nonascii_setgetdelete(client): assert client.json().set("notascii", Path.root_path(), "hyvää-élève") -- cgit v1.2.1