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)); + } + }