Skip to content

Commit c5ab6bb

Browse files
KoKimSSa-TODO-rov
andauthored
Add String-based JSON API to avoid unnecessary conversions (#3369) (#3394)
* Add String-based JSON API to avoid unnecessary conversions #3369 - Add String overloads for jsonArrappend, jsonArrindex, jsonArrinsert - Add String overloads for jsonMerge, jsonSet, jsonStrappend - Implement direct String-to-bytes conversion in RedisJsonCommandBuilder - Update Async, Reactive, and Sync interfaces consistently - Eliminate String → JsonValue → String → bytes conversion overhead * Add comprehensive tests for String JSON API #3369 - Add unit tests for all String overload methods - Verify direct string encoding optimization - Test both custom JsonPath and ROOT_PATH scenarios - Validate command construction for all String-based JSON operations * Polish JSON API documentation and formatting #3369 - Remove JavaDoc comments from RedisJsonCommandBuilder String methods to match class conventions - Update @author entries to use full names (SeungSu Kim) - Fix @SInCE annotation from 6.5 to 6.9 for new String overload methods - Restore blank lines and fix spacing to maintain consistent formatting - Align documentation style with existing codebase patterns * CAE-1404 - finish String extension for JSON API * Fix since annotation on json string API * Rm useless comments in implementations and mark methods as Override * Rm more comments. * Format --------- Co-authored-by: aleksandar.todorov <[email protected]>
1 parent 501ed9d commit c5ab6bb

13 files changed

+1228
-3
lines changed

src/main/java/io/lettuce/core/AbstractRedisAsyncCommands.java

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@
8989
* @author dengliming
9090
* @author Andrey Shlykov
9191
* @author Ali Takavci
92+
* @author SeugnSu Kim
9293
*/
9394
@SuppressWarnings("unchecked")
9495
public abstract class AbstractRedisAsyncCommands<K, V> implements RedisAclAsyncCommands<K, V>, RedisHashAsyncCommands<K, V>,
@@ -1737,6 +1738,16 @@ public RedisFuture<List<Long>> jsonArrappend(K key, JsonValue... values) {
17371738
return dispatch(jsonCommandBuilder.jsonArrappend(key, JsonPath.ROOT_PATH, values));
17381739
}
17391740

1741+
@Override
1742+
public RedisFuture<List<Long>> jsonArrappend(K key, JsonPath jsonPath, String... jsonStrings) {
1743+
return dispatch(jsonCommandBuilder.jsonArrappend(key, jsonPath, jsonStrings));
1744+
}
1745+
1746+
@Override
1747+
public RedisFuture<List<Long>> jsonArrappend(K key, String... jsonStrings) {
1748+
return dispatch(jsonCommandBuilder.jsonArrappend(key, JsonPath.ROOT_PATH, jsonStrings));
1749+
}
1750+
17401751
@Override
17411752
public RedisFuture<List<Long>> jsonArrindex(K key, JsonPath jsonPath, JsonValue value, JsonRangeArgs range) {
17421753
return dispatch(jsonCommandBuilder.jsonArrindex(key, jsonPath, value, range));
@@ -1747,11 +1758,26 @@ public RedisFuture<List<Long>> jsonArrindex(K key, JsonPath jsonPath, JsonValue
17471758
return dispatch(jsonCommandBuilder.jsonArrindex(key, jsonPath, value, JsonRangeArgs.Builder.defaults()));
17481759
}
17491760

1761+
@Override
1762+
public RedisFuture<List<Long>> jsonArrindex(K key, JsonPath jsonPath, String jsonString, JsonRangeArgs range) {
1763+
return dispatch(jsonCommandBuilder.jsonArrindex(key, jsonPath, jsonString, range));
1764+
}
1765+
1766+
@Override
1767+
public RedisFuture<List<Long>> jsonArrindex(K key, JsonPath jsonPath, String jsonString) {
1768+
return dispatch(jsonCommandBuilder.jsonArrindex(key, jsonPath, jsonString, JsonRangeArgs.Builder.defaults()));
1769+
}
1770+
17501771
@Override
17511772
public RedisFuture<List<Long>> jsonArrinsert(K key, JsonPath jsonPath, int index, JsonValue... values) {
17521773
return dispatch(jsonCommandBuilder.jsonArrinsert(key, jsonPath, index, values));
17531774
}
17541775

1776+
@Override
1777+
public RedisFuture<List<Long>> jsonArrinsert(K key, JsonPath jsonPath, int index, String... jsonStrings) {
1778+
return dispatch(jsonCommandBuilder.jsonArrinsert(key, jsonPath, index, jsonStrings));
1779+
}
1780+
17551781
@Override
17561782
public RedisFuture<List<Long>> jsonArrlen(K key, JsonPath jsonPath) {
17571783
return dispatch(jsonCommandBuilder.jsonArrlen(key, jsonPath));
@@ -1817,6 +1843,11 @@ public RedisFuture<String> jsonMerge(K key, JsonPath jsonPath, JsonValue value)
18171843
return dispatch(jsonCommandBuilder.jsonMerge(key, jsonPath, value));
18181844
}
18191845

1846+
@Override
1847+
public RedisFuture<String> jsonMerge(K key, JsonPath jsonPath, String jsonString) {
1848+
return dispatch(jsonCommandBuilder.jsonMerge(key, jsonPath, jsonString));
1849+
}
1850+
18201851
@Override
18211852
public RedisFuture<List<JsonValue>> jsonMGet(JsonPath jsonPath, K... keys) {
18221853
return dispatch(jsonCommandBuilder.jsonMGet(jsonPath, keys));
@@ -1862,6 +1893,16 @@ public RedisFuture<String> jsonSet(K key, JsonPath jsonPath, JsonValue value) {
18621893
return dispatch(jsonCommandBuilder.jsonSet(key, jsonPath, value, JsonSetArgs.Builder.defaults()));
18631894
}
18641895

1896+
@Override
1897+
public RedisFuture<String> jsonSet(K key, JsonPath jsonPath, String jsonString, JsonSetArgs options) {
1898+
return dispatch(jsonCommandBuilder.jsonSet(key, jsonPath, jsonString, options));
1899+
}
1900+
1901+
@Override
1902+
public RedisFuture<String> jsonSet(K key, JsonPath jsonPath, String jsonString) {
1903+
return dispatch(jsonCommandBuilder.jsonSet(key, jsonPath, jsonString, JsonSetArgs.Builder.defaults()));
1904+
}
1905+
18651906
@Override
18661907
public RedisFuture<List<Long>> jsonStrappend(K key, JsonPath jsonPath, JsonValue value) {
18671908
return dispatch(jsonCommandBuilder.jsonStrappend(key, jsonPath, value));
@@ -1872,6 +1913,16 @@ public RedisFuture<List<Long>> jsonStrappend(K key, JsonValue value) {
18721913
return dispatch(jsonCommandBuilder.jsonStrappend(key, JsonPath.ROOT_PATH, value));
18731914
}
18741915

1916+
@Override
1917+
public RedisFuture<List<Long>> jsonStrappend(K key, JsonPath jsonPath, String jsonString) {
1918+
return dispatch(jsonCommandBuilder.jsonStrappend(key, jsonPath, jsonString));
1919+
}
1920+
1921+
@Override
1922+
public RedisFuture<List<Long>> jsonStrappend(K key, String jsonString) {
1923+
return dispatch(jsonCommandBuilder.jsonStrappend(key, JsonPath.ROOT_PATH, jsonString));
1924+
}
1925+
18751926
@Override
18761927
public RedisFuture<List<Long>> jsonStrlen(K key, JsonPath jsonPath) {
18771928
return dispatch(jsonCommandBuilder.jsonStrlen(key, jsonPath));

src/main/java/io/lettuce/core/AbstractRedisReactiveCommands.java

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@
9898
* @author Andrey Shlykov
9999
* @author Ali Takavci
100100
* @author Tihomir Mateev
101+
* @author SeugnSu Kim
101102
* @since 4.0
102103
*/
103104
public abstract class AbstractRedisReactiveCommands<K, V>
@@ -1802,6 +1803,16 @@ public Flux<Long> jsonArrappend(K key, JsonValue... values) {
18021803
return createDissolvingFlux(() -> jsonCommandBuilder.jsonArrappend(key, JsonPath.ROOT_PATH, values));
18031804
}
18041805

1806+
@Override
1807+
public Flux<Long> jsonArrappend(K key, JsonPath jsonPath, String... jsonStrings) {
1808+
return createDissolvingFlux(() -> jsonCommandBuilder.jsonArrappend(key, jsonPath, jsonStrings));
1809+
}
1810+
1811+
@Override
1812+
public Flux<Long> jsonArrappend(K key, String... jsonStrings) {
1813+
return createDissolvingFlux(() -> jsonCommandBuilder.jsonArrappend(key, JsonPath.ROOT_PATH, jsonStrings));
1814+
}
1815+
18051816
@Override
18061817
public Flux<Long> jsonArrindex(K key, JsonPath jsonPath, JsonValue value, JsonRangeArgs range) {
18071818
return createDissolvingFlux(() -> jsonCommandBuilder.jsonArrindex(key, jsonPath, value, range));
@@ -1813,11 +1824,27 @@ public Flux<Long> jsonArrindex(K key, JsonPath jsonPath, JsonValue value) {
18131824
return createDissolvingFlux(() -> jsonCommandBuilder.jsonArrindex(key, jsonPath, value, args));
18141825
}
18151826

1827+
@Override
1828+
public Flux<Long> jsonArrindex(K key, JsonPath jsonPath, String jsonString, JsonRangeArgs range) {
1829+
return createDissolvingFlux(() -> jsonCommandBuilder.jsonArrindex(key, jsonPath, jsonString, range));
1830+
}
1831+
1832+
@Override
1833+
public Flux<Long> jsonArrindex(K key, JsonPath jsonPath, String jsonString) {
1834+
return createDissolvingFlux(
1835+
() -> jsonCommandBuilder.jsonArrindex(key, jsonPath, jsonString, JsonRangeArgs.Builder.defaults()));
1836+
}
1837+
18161838
@Override
18171839
public Flux<Long> jsonArrinsert(K key, JsonPath jsonPath, int index, JsonValue... values) {
18181840
return createDissolvingFlux(() -> jsonCommandBuilder.jsonArrinsert(key, jsonPath, index, values));
18191841
}
18201842

1843+
@Override
1844+
public Flux<Long> jsonArrinsert(K key, JsonPath jsonPath, int index, String... jsonStrings) {
1845+
return createDissolvingFlux(() -> jsonCommandBuilder.jsonArrinsert(key, jsonPath, index, jsonStrings));
1846+
}
1847+
18211848
@Override
18221849
public Flux<Long> jsonArrlen(K key, JsonPath jsonPath) {
18231850
return createDissolvingFlux(() -> jsonCommandBuilder.jsonArrlen(key, jsonPath));
@@ -1884,6 +1911,11 @@ public Mono<String> jsonMerge(K key, JsonPath jsonPath, JsonValue value) {
18841911
return createMono(() -> jsonCommandBuilder.jsonMerge(key, jsonPath, value));
18851912
}
18861913

1914+
@Override
1915+
public Mono<String> jsonMerge(K key, JsonPath jsonPath, String jsonString) {
1916+
return createMono(() -> jsonCommandBuilder.jsonMerge(key, jsonPath, jsonString));
1917+
}
1918+
18871919
@Override
18881920
public Flux<JsonValue> jsonMGet(JsonPath jsonPath, K... keys) {
18891921
return createDissolvingFlux(() -> jsonCommandBuilder.jsonMGet(jsonPath, keys));
@@ -1930,6 +1962,16 @@ public Mono<String> jsonSet(K key, JsonPath jsonPath, JsonValue value) {
19301962
return createMono(() -> jsonCommandBuilder.jsonSet(key, jsonPath, value, args));
19311963
}
19321964

1965+
@Override
1966+
public Mono<String> jsonSet(K key, JsonPath jsonPath, String jsonString, JsonSetArgs options) {
1967+
return createMono(() -> jsonCommandBuilder.jsonSet(key, jsonPath, jsonString, options));
1968+
}
1969+
1970+
@Override
1971+
public Mono<String> jsonSet(K key, JsonPath jsonPath, String jsonString) {
1972+
return createMono(() -> jsonCommandBuilder.jsonSet(key, jsonPath, jsonString, JsonSetArgs.Builder.defaults()));
1973+
}
1974+
19331975
@Override
19341976
public Flux<Long> jsonStrappend(K key, JsonPath jsonPath, JsonValue value) {
19351977
return createDissolvingFlux(() -> jsonCommandBuilder.jsonStrappend(key, jsonPath, value));
@@ -1940,6 +1982,16 @@ public Flux<Long> jsonStrappend(K key, JsonValue value) {
19401982
return createDissolvingFlux(() -> jsonCommandBuilder.jsonStrappend(key, JsonPath.ROOT_PATH, value));
19411983
}
19421984

1985+
@Override
1986+
public Flux<Long> jsonStrappend(K key, JsonPath jsonPath, String jsonString) {
1987+
return createDissolvingFlux(() -> jsonCommandBuilder.jsonStrappend(key, jsonPath, jsonString));
1988+
}
1989+
1990+
@Override
1991+
public Flux<Long> jsonStrappend(K key, String jsonString) {
1992+
return createDissolvingFlux(() -> jsonCommandBuilder.jsonStrappend(key, JsonPath.ROOT_PATH, jsonString));
1993+
}
1994+
19431995
@Override
19441996
public Flux<Long> jsonStrlen(K key, JsonPath jsonPath) {
19451997
return createDissolvingFlux(() -> jsonCommandBuilder.jsonStrlen(key, jsonPath));

src/main/java/io/lettuce/core/RedisJsonCommandBuilder.java

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
* Implementation of the {@link BaseRedisCommandBuilder} handling JSON commands.
3131
*
3232
* @author Tihomir Mateev
33+
* @author SeugnSu Kim
3334
* @since 6.5
3435
*/
3536
class RedisJsonCommandBuilder<K, V> extends BaseRedisCommandBuilder<K, V> {
@@ -58,6 +59,23 @@ Command<K, V, List<Long>> jsonArrappend(K key, JsonPath jsonPath, JsonValue... j
5859
return createCommand(JSON_ARRAPPEND, (CommandOutput) new ArrayOutput<>(codec), args);
5960
}
6061

62+
Command<K, V, List<Long>> jsonArrappend(K key, JsonPath jsonPath, String... jsonValues) {
63+
notNullKey(key);
64+
65+
CommandArgs<K, V> args = new CommandArgs<>(codec).addKey(key);
66+
67+
if (jsonPath != null && !jsonPath.isRootPath()) {
68+
// OPTIONAL as per API
69+
args.add(jsonPath.toString());
70+
}
71+
72+
for (String value : jsonValues) {
73+
args.add(value);
74+
}
75+
76+
return createCommand(JSON_ARRAPPEND, (CommandOutput) new ArrayOutput<>(codec), args);
77+
}
78+
6179
Command<K, V, List<Long>> jsonArrindex(K key, JsonPath jsonPath, JsonValue value, JsonRangeArgs range) {
6280
notNullKey(key);
6381

@@ -74,6 +92,22 @@ Command<K, V, List<Long>> jsonArrindex(K key, JsonPath jsonPath, JsonValue value
7492
return createCommand(JSON_ARRINDEX, (CommandOutput) new ArrayOutput<>(codec), args);
7593
}
7694

95+
Command<K, V, List<Long>> jsonArrindex(K key, JsonPath jsonPath, String value, JsonRangeArgs range) {
96+
notNullKey(key);
97+
98+
CommandArgs<K, V> args = new CommandArgs<>(codec).addKey(key);
99+
100+
args.add(jsonPath.toString());
101+
args.add(value);
102+
103+
if (range != null) {
104+
// OPTIONAL as per API
105+
range.build(args);
106+
}
107+
108+
return createCommand(JSON_ARRINDEX, (CommandOutput) new ArrayOutput<>(codec), args);
109+
}
110+
77111
Command<K, V, List<Long>> jsonArrinsert(K key, JsonPath jsonPath, int index, JsonValue... values) {
78112
notNullKey(key);
79113

@@ -89,6 +123,21 @@ Command<K, V, List<Long>> jsonArrinsert(K key, JsonPath jsonPath, int index, Jso
89123
return createCommand(JSON_ARRINSERT, (CommandOutput) new ArrayOutput<>(codec), args);
90124
}
91125

126+
Command<K, V, List<Long>> jsonArrinsert(K key, JsonPath jsonPath, int index, String... values) {
127+
notNullKey(key);
128+
129+
CommandArgs<K, V> args = new CommandArgs<>(codec).addKey(key);
130+
131+
args.add(jsonPath.toString());
132+
args.add(index);
133+
134+
for (String value : values) {
135+
args.add(value);
136+
}
137+
138+
return createCommand(JSON_ARRINSERT, (CommandOutput) new ArrayOutput<>(codec), args);
139+
}
140+
92141
Command<K, V, List<Long>> jsonArrlen(K key, JsonPath jsonPath) {
93142
notNullKey(key);
94143

@@ -180,6 +229,16 @@ Command<K, V, String> jsonMerge(K key, JsonPath jsonPath, JsonValue value) {
180229
return createCommand(JSON_MERGE, new StatusOutput<>(codec), args);
181230
}
182231

232+
Command<K, V, String> jsonMerge(K key, JsonPath jsonPath, String value) {
233+
notNullKey(key);
234+
235+
CommandArgs<K, V> args = new CommandArgs<>(codec).addKey(key);
236+
args.add(jsonPath.toString());
237+
args.add(value);
238+
239+
return createCommand(JSON_MERGE, new StatusOutput<>(codec), args);
240+
}
241+
183242
Command<K, V, List<JsonValue>> jsonMGet(JsonPath jsonPath, K... keys) {
184243
notEmpty(keys);
185244

@@ -256,6 +315,22 @@ Command<K, V, String> jsonSet(K key, JsonPath jsonPath, JsonValue value, JsonSet
256315
return createCommand(JSON_SET, new StatusOutput<>(codec), args);
257316
}
258317

318+
Command<K, V, String> jsonSet(K key, JsonPath jsonPath, String value, JsonSetArgs options) {
319+
notNullKey(key);
320+
321+
CommandArgs<K, V> args = new CommandArgs<>(codec).addKey(key);
322+
323+
args.add(jsonPath.toString());
324+
args.add(value);
325+
326+
if (options != null) {
327+
// OPTIONAL as per API
328+
options.build(args);
329+
}
330+
331+
return createCommand(JSON_SET, new StatusOutput<>(codec), args);
332+
}
333+
259334
Command<K, V, List<Long>> jsonStrappend(K key, JsonPath jsonPath, JsonValue value) {
260335
notNullKey(key);
261336

@@ -271,6 +346,20 @@ Command<K, V, List<Long>> jsonStrappend(K key, JsonPath jsonPath, JsonValue valu
271346
return createCommand(JSON_STRAPPEND, (CommandOutput) new ArrayOutput<>(codec), args);
272347
}
273348

349+
Command<K, V, List<Long>> jsonStrappend(K key, JsonPath jsonPath, String jsonString) {
350+
notNullKey(key);
351+
352+
CommandArgs<K, V> args = new CommandArgs<>(codec).addKey(key);
353+
354+
if (jsonPath != null && !jsonPath.isRootPath()) {
355+
args.add(jsonPath.toString());
356+
}
357+
358+
args.add(jsonString.getBytes());
359+
360+
return createCommand(JSON_STRAPPEND, (CommandOutput) new ArrayOutput<>(codec), args);
361+
}
362+
274363
Command<K, V, List<Long>> jsonStrlen(K key, JsonPath jsonPath) {
275364

276365
notNullKey(key);

0 commit comments

Comments
 (0)