From 5b93cc41bd30ed8dd0498ded5a06a7ac7a6ab745 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=98=E5=85=B8?= Date: Sun, 9 Aug 2026 15:36:50 +0800 Subject: [PATCH] fix: normalize negative indices in bounded array slice expressions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ArraySliceToken.sliceBetween only clamped the upper bound (`to = Math.min(length, to)`), so a negative `from` or `to` was not resolved against the array length — unlike sliceFrom and sliceTo, which both do `index = length + index` for negatives. As a result e.g. `$[-2:4]` on a 5-element array looped from -2 and wrapped around to `[3,4,0,1,2,3]` (duplicated), and `$[1:-1]` returned an empty list (#1076). Mirror the sibling normalization in sliceBetween so negative `from`/`to` are resolved against the length before slicing. Closes #1076 Signed-off-by: 付典 --- .../internal/path/ArraySliceToken.java | 9 ++++++++ .../jayway/jsonpath/old/ArraySlicingTest.java | 21 +++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/path/ArraySliceToken.java b/json-path/src/main/java/com/jayway/jsonpath/internal/path/ArraySliceToken.java index af43e7ebf..ae3441545 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/path/ArraySliceToken.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/path/ArraySliceToken.java @@ -69,6 +69,15 @@ private void sliceBetween(String currentPath, PathRef parent, Object model, Eval int from = operation.from(); int to = operation.to(); + if (from < 0) { + //calculate slice start from array length + from = length + from; + } + from = Math.max(0, from); + if (to < 0) { + //calculate slice end from array length + to = length + to; + } to = Math.min(length, to); if (from >= to || length == 0) { diff --git a/json-path/src/test/java/com/jayway/jsonpath/old/ArraySlicingTest.java b/json-path/src/test/java/com/jayway/jsonpath/old/ArraySlicingTest.java index 41556e930..2e12b5dde 100644 --- a/json-path/src/test/java/com/jayway/jsonpath/old/ArraySlicingTest.java +++ b/json-path/src/test/java/com/jayway/jsonpath/old/ArraySlicingTest.java @@ -86,4 +86,25 @@ public void get_indexes() { assertThat(result, Matchers.contains(1, 3, 5)); } + + @Test + public void slice_between_with_negative_from() { + // Negative "from" must be normalized against the array length, like sliceFrom. + // $[-2:4] on a 5-element array -> from index 3, to index 4 -> [3] (#1076). + // Previously "from" was not normalized, so the slice looped from -2 and + // wrapped around, producing a duplicated/shifted result. + List result = JsonPath.read("[0, 1, 2, 3, 4]", "$[-2:4]"); + assertThat(result, Matchers.contains(3)); + } + + @Test + public void slice_between_with_negative_to() { + // Negative "to" must be normalized against the array length, like sliceTo. + // $[1:-1] on a 5-element array -> from 1, to 4 -> [1, 2, 3] (#1076). + // Previously "to" was only clamped via Math.min(length, to), so a negative + // "to" made from >= to and returned an empty list. + List result = JsonPath.read("[0, 1, 2, 3, 4]", "$[1:-1]"); + assertThat(result, Matchers.contains(1, 2, 3)); + } + }