diff --git a/release-notes/CREDITS-2.x b/release-notes/CREDITS-2.x index 0b6bacab87..2b5c261794 100644 --- a/release-notes/CREDITS-2.x +++ b/release-notes/CREDITS-2.x @@ -352,22 +352,24 @@ Chris Rankin (chrisr3@github) (2.15.1) Przemyslaw Gomulka (pgomulka@github) - * Contributed #882: Allow TokenFIlter to skip last elements in arrays + * Contributed #882: Allow TokenFIlter to skip last elements in arrays (2.14.2) Markus Spika (DemonicTutor@github) - * Contributed #890: `FilteringGeneratorDelegate` does not create new `filterContext` + * Contributed #890: `FilteringGeneratorDelegate` does not create new `filterContext` if `tokenFilter` is null (2.14.2) + * Contributed #1036: Allow all array elements in `JsonPointerBasedFilter` + (2.16.0) Pedro Nacht (pnacht@github) - * Contributed #844: Add SLSA provenance via build script + * Contributed #844: Add SLSA provenance via build script (2.15.0) Jonas Konrad (yawkat@github) - * Contributed #921: Add `JsonFactory.Feature` to disable charset detection + * Contributed #921: Add `JsonFactory.Feature` to disable charset detection (2.15.0) Carter Kozak (carterkozak@github) - * Contributed #1015: `JsonFactory` implementations should respect `CANONICALIZE_FIELD_NAMES` + * Contributed #1015: `JsonFactory` implementations should respect `CANONICALIZE_FIELD_NAMES` (2.15.1) diff --git a/release-notes/VERSION-2.x b/release-notes/VERSION-2.x index a8c63d140c..4595114344 100644 --- a/release-notes/VERSION-2.x +++ b/release-notes/VERSION-2.x @@ -21,6 +21,8 @@ a pure JSON library. (contributed by Carter K) #1035: Root cause for failing test for `testMangledIntsBytes()` in `ParserErrorHandlingTest` (reported by @harsha-99) +#1036: Allow all array elements in `JsonPointerBasedFilter` + (contribited by Markus S) 2.15.2 (not yet released) diff --git a/src/main/java/com/fasterxml/jackson/core/filter/JsonPointerBasedFilter.java b/src/main/java/com/fasterxml/jackson/core/filter/JsonPointerBasedFilter.java index ea0b3dcd79..74df9c9ef5 100644 --- a/src/main/java/com/fasterxml/jackson/core/filter/JsonPointerBasedFilter.java +++ b/src/main/java/com/fasterxml/jackson/core/filter/JsonPointerBasedFilter.java @@ -14,24 +14,52 @@ public class JsonPointerBasedFilter extends TokenFilter { protected final JsonPointer _pathToMatch; + /** + * If true include all array elements by ignoring the array index match and advancing + * the JsonPointer to the next level + * + * @since 2.16 + */ + protected final boolean _includeAllElements; + public JsonPointerBasedFilter(String ptrExpr) { - this(JsonPointer.compile(ptrExpr)); + this(JsonPointer.compile(ptrExpr), false); + } + + /** + * @param pathToMatch Content to extract + */ + public JsonPointerBasedFilter(JsonPointer pathToMatch) { + this(pathToMatch, false); } - public JsonPointerBasedFilter(JsonPointer match) { - _pathToMatch = match; + /** + * @param pathToMatch Content to extract + * @param includeAllElements if true array indexes in ptrExpr are ignored + * and all elements will be matched. default: false + * + * @since 2.16 + */ + public JsonPointerBasedFilter(JsonPointer pathToMatch, boolean includeAllElements) { + _pathToMatch = pathToMatch; + _includeAllElements = includeAllElements; } @Override public TokenFilter includeElement(int index) { - JsonPointer next = _pathToMatch.matchElement(index); + JsonPointer next; + if (_includeAllElements && !_pathToMatch.mayMatchElement()) { + next = _pathToMatch.tail(); + } else { + next = _pathToMatch.matchElement(index); + } if (next == null) { return null; } if (next.matches()) { return TokenFilter.INCLUDE_ALL; } - return new JsonPointerBasedFilter(next); + return new JsonPointerBasedFilter(next, _includeAllElements); } @Override @@ -43,7 +71,7 @@ public TokenFilter includeProperty(String name) { if (next.matches()) { return TokenFilter.INCLUDE_ALL; } - return new JsonPointerBasedFilter(next); + return new JsonPointerBasedFilter(next, _includeAllElements); } @Override diff --git a/src/test/java/com/fasterxml/jackson/core/filter/GeneratorFiltering890Test.java b/src/test/java/com/fasterxml/jackson/core/filter/GeneratorFiltering890Test.java index c8e7ebc041..579bdabfd2 100644 --- a/src/test/java/com/fasterxml/jackson/core/filter/GeneratorFiltering890Test.java +++ b/src/test/java/com/fasterxml/jackson/core/filter/GeneratorFiltering890Test.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.core.BaseTest; import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonPointer; import com.fasterxml.jackson.core.filter.TokenFilter.Inclusion; import java.io.ByteArrayOutputStream; @@ -26,7 +27,7 @@ private OrTokenFilter(final List delegates) { } static OrTokenFilter create(final Set jsonPointers) { - return new OrTokenFilter(jsonPointers.stream().map(JsonPointerBasedFilter::new).collect(Collectors.toList())); + return new OrTokenFilter(jsonPointers.stream().map(p -> new JsonPointerBasedFilter(JsonPointer.compile(p), true)).collect(Collectors.toList())); } @Override @@ -69,7 +70,7 @@ private TokenFilter executeDelegates(final UnaryOperator operator) } } - public void testIssue809_singleProperty() throws Exception + public void testIssue890_singleProperty() throws Exception { // GIVEN final Set jsonPointers = Stream.of("/0/id").collect(Collectors.toSet()); @@ -91,7 +92,7 @@ public void testIssue809_singleProperty() throws Exception assertEquals("[{\"id\":1}]", json); } - public void testIssue809_twoProperties() throws Exception + public void testIssue890_twoProperties() throws Exception { // GIVEN final Set jsonPointers = Stream.of("/0/id", "/0/stuff/0/name").collect(Collectors.toSet()); @@ -113,6 +114,28 @@ public void testIssue809_twoProperties() throws Exception assertEquals("[{\"id\":1,\"stuff\":[{\"name\":\"first\"}]}]", json); } + public void testIssue890_fullArray() throws Exception + { + // GIVEN + final Set jsonPointers = Stream.of("//id", "//stuff//name").collect(Collectors.toSet()); + + // WHEN + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + JsonGenerator g = new FilteringGeneratorDelegate(createGenerator(outputStream), OrTokenFilter.create(jsonPointers), Inclusion.INCLUDE_ALL_AND_PATH, true); + + g.writeStartArray(); + writeOuterObject(g, 1, "first", "a", "second", "b"); + writeOuterObject(g, 2, "third", "c", "fourth", "d"); + g.writeEndArray(); + g.flush(); + g.close(); + outputStream.close(); + + // THEN + String json = outputStream.toString("US-ASCII"); + assertEquals("[{\"id\":1,\"stuff\":[{\"name\":\"first\"},{\"name\":\"second\"}]},{\"id\":2,\"stuff\":[{\"name\":\"third\"},{\"name\":\"fourth\"}]}]", json); + } + private static void writeOuterObject(final JsonGenerator g, final int id, final String name1, final String type1, final String name2, final String type2) throws IOException { g.writeStartObject();