Skip to content

Commit e85e2d5

Browse files
authored
Allow all array elements in JsonPointerBasedFilter (#1036)
1 parent d9b72a5 commit e85e2d5

File tree

4 files changed

+69
-14
lines changed

4 files changed

+69
-14
lines changed

release-notes/CREDITS-2.x

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -352,22 +352,24 @@ Chris Rankin (chrisr3@github)
352352
(2.15.1)
353353

354354
Przemyslaw Gomulka (pgomulka@github)
355-
* Contributed #882: Allow TokenFIlter to skip last elements in arrays
355+
* Contributed #882: Allow TokenFIlter to skip last elements in arrays
356356
(2.14.2)
357357

358358
Markus Spika (DemonicTutor@github)
359-
* Contributed #890: `FilteringGeneratorDelegate` does not create new `filterContext`
359+
* Contributed #890: `FilteringGeneratorDelegate` does not create new `filterContext`
360360
if `tokenFilter` is null
361361
(2.14.2)
362+
* Contributed #1036: Allow all array elements in `JsonPointerBasedFilter`
363+
(2.16.0)
362364

363365
Pedro Nacht (pnacht@github)
364-
* Contributed #844: Add SLSA provenance via build script
366+
* Contributed #844: Add SLSA provenance via build script
365367
(2.15.0)
366368

367369
Jonas Konrad (yawkat@github)
368-
* Contributed #921: Add `JsonFactory.Feature` to disable charset detection
370+
* Contributed #921: Add `JsonFactory.Feature` to disable charset detection
369371
(2.15.0)
370372

371373
Carter Kozak (carterkozak@github)
372-
* Contributed #1015: `JsonFactory` implementations should respect `CANONICALIZE_FIELD_NAMES`
374+
* Contributed #1015: `JsonFactory` implementations should respect `CANONICALIZE_FIELD_NAMES`
373375
(2.15.1)

release-notes/VERSION-2.x

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ a pure JSON library.
2121
(contributed by Carter K)
2222
#1035: Root cause for failing test for `testMangledIntsBytes()` in `ParserErrorHandlingTest`
2323
(reported by @harsha-99)
24+
#1036: Allow all array elements in `JsonPointerBasedFilter`
25+
(contribited by Markus S)
2426

2527
2.15.2 (not yet released)
2628

src/main/java/com/fasterxml/jackson/core/filter/JsonPointerBasedFilter.java

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,24 +14,52 @@ public class JsonPointerBasedFilter extends TokenFilter
1414
{
1515
protected final JsonPointer _pathToMatch;
1616

17+
/**
18+
* If true include all array elements by ignoring the array index match and advancing
19+
* the JsonPointer to the next level
20+
*
21+
* @since 2.16
22+
*/
23+
protected final boolean _includeAllElements;
24+
1725
public JsonPointerBasedFilter(String ptrExpr) {
18-
this(JsonPointer.compile(ptrExpr));
26+
this(JsonPointer.compile(ptrExpr), false);
27+
}
28+
29+
/**
30+
* @param pathToMatch Content to extract
31+
*/
32+
public JsonPointerBasedFilter(JsonPointer pathToMatch) {
33+
this(pathToMatch, false);
1934
}
2035

21-
public JsonPointerBasedFilter(JsonPointer match) {
22-
_pathToMatch = match;
36+
/**
37+
* @param pathToMatch Content to extract
38+
* @param includeAllElements if true array indexes in <code>ptrExpr</code> are ignored
39+
* and all elements will be matched. default: false
40+
*
41+
* @since 2.16
42+
*/
43+
public JsonPointerBasedFilter(JsonPointer pathToMatch, boolean includeAllElements) {
44+
_pathToMatch = pathToMatch;
45+
_includeAllElements = includeAllElements;
2346
}
2447

2548
@Override
2649
public TokenFilter includeElement(int index) {
27-
JsonPointer next = _pathToMatch.matchElement(index);
50+
JsonPointer next;
51+
if (_includeAllElements && !_pathToMatch.mayMatchElement()) {
52+
next = _pathToMatch.tail();
53+
} else {
54+
next = _pathToMatch.matchElement(index);
55+
}
2856
if (next == null) {
2957
return null;
3058
}
3159
if (next.matches()) {
3260
return TokenFilter.INCLUDE_ALL;
3361
}
34-
return new JsonPointerBasedFilter(next);
62+
return new JsonPointerBasedFilter(next, _includeAllElements);
3563
}
3664

3765
@Override
@@ -43,7 +71,7 @@ public TokenFilter includeProperty(String name) {
4371
if (next.matches()) {
4472
return TokenFilter.INCLUDE_ALL;
4573
}
46-
return new JsonPointerBasedFilter(next);
74+
return new JsonPointerBasedFilter(next, _includeAllElements);
4775
}
4876

4977
@Override

src/test/java/com/fasterxml/jackson/core/filter/GeneratorFiltering890Test.java

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.fasterxml.jackson.core.BaseTest;
44
import com.fasterxml.jackson.core.JsonGenerator;
5+
import com.fasterxml.jackson.core.JsonPointer;
56
import com.fasterxml.jackson.core.filter.TokenFilter.Inclusion;
67

78
import java.io.ByteArrayOutputStream;
@@ -26,7 +27,7 @@ private OrTokenFilter(final List<? extends TokenFilter> delegates) {
2627
}
2728

2829
static OrTokenFilter create(final Set<String> jsonPointers) {
29-
return new OrTokenFilter(jsonPointers.stream().map(JsonPointerBasedFilter::new).collect(Collectors.toList()));
30+
return new OrTokenFilter(jsonPointers.stream().map(p -> new JsonPointerBasedFilter(JsonPointer.compile(p), true)).collect(Collectors.toList()));
3031
}
3132

3233
@Override
@@ -69,7 +70,7 @@ private TokenFilter executeDelegates(final UnaryOperator<TokenFilter> operator)
6970
}
7071
}
7172

72-
public void testIssue809_singleProperty() throws Exception
73+
public void testIssue890_singleProperty() throws Exception
7374
{
7475
// GIVEN
7576
final Set<String> jsonPointers = Stream.of("/0/id").collect(Collectors.toSet());
@@ -91,7 +92,7 @@ public void testIssue809_singleProperty() throws Exception
9192
assertEquals("[{\"id\":1}]", json);
9293
}
9394

94-
public void testIssue809_twoProperties() throws Exception
95+
public void testIssue890_twoProperties() throws Exception
9596
{
9697
// GIVEN
9798
final Set<String> jsonPointers = Stream.of("/0/id", "/0/stuff/0/name").collect(Collectors.toSet());
@@ -113,6 +114,28 @@ public void testIssue809_twoProperties() throws Exception
113114
assertEquals("[{\"id\":1,\"stuff\":[{\"name\":\"first\"}]}]", json);
114115
}
115116

117+
public void testIssue890_fullArray() throws Exception
118+
{
119+
// GIVEN
120+
final Set<String> jsonPointers = Stream.of("//id", "//stuff//name").collect(Collectors.toSet());
121+
122+
// WHEN
123+
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
124+
JsonGenerator g = new FilteringGeneratorDelegate(createGenerator(outputStream), OrTokenFilter.create(jsonPointers), Inclusion.INCLUDE_ALL_AND_PATH, true);
125+
126+
g.writeStartArray();
127+
writeOuterObject(g, 1, "first", "a", "second", "b");
128+
writeOuterObject(g, 2, "third", "c", "fourth", "d");
129+
g.writeEndArray();
130+
g.flush();
131+
g.close();
132+
outputStream.close();
133+
134+
// THEN
135+
String json = outputStream.toString("US-ASCII");
136+
assertEquals("[{\"id\":1,\"stuff\":[{\"name\":\"first\"},{\"name\":\"second\"}]},{\"id\":2,\"stuff\":[{\"name\":\"third\"},{\"name\":\"fourth\"}]}]", json);
137+
}
138+
116139
private static void writeOuterObject(final JsonGenerator g, final int id, final String name1, final String type1, final String name2, final String type2) throws IOException
117140
{
118141
g.writeStartObject();

0 commit comments

Comments
 (0)