diff --git a/src/main/java/tools/jackson/core/filter/JsonPointerBasedFilter.java b/src/main/java/tools/jackson/core/filter/JsonPointerBasedFilter.java index e96367bc57..fa3cef54f1 100644 --- a/src/main/java/tools/jackson/core/filter/JsonPointerBasedFilter.java +++ b/src/main/java/tools/jackson/core/filter/JsonPointerBasedFilter.java @@ -13,25 +13,47 @@ 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 + */ + protected final boolean _includeAllElements; public JsonPointerBasedFilter(String ptrExpr) { - this(JsonPointer.compile(ptrExpr)); + this(JsonPointer.compile(ptrExpr), false); } public JsonPointerBasedFilter(JsonPointer match) { + this(match, false); + } + + /** + * @param ptrExpr to extract. + * @param includeAllElements if true array indexes in ptrExpr are ignored and all elements will be matched. default: false + */ + public JsonPointerBasedFilter(String ptrExpr, boolean includeAllElements) { + this(JsonPointer.compile(ptrExpr), includeAllElements); + } + + public JsonPointerBasedFilter(JsonPointer match, boolean includeAllElements) { _pathToMatch = match; + _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 +65,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/tools/jackson/core/filter/GeneratorFiltering890Test.java b/src/test/java/tools/jackson/core/filter/GeneratorFiltering890Test.java index 7ff2b48f90..23c6216167 100644 --- a/src/test/java/tools/jackson/core/filter/GeneratorFiltering890Test.java +++ b/src/test/java/tools/jackson/core/filter/GeneratorFiltering890Test.java @@ -23,7 +23,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(p, true)).collect(Collectors.toList())); } @Override @@ -110,6 +110,28 @@ public void testIssue809_twoProperties() throws Exception assertEquals("[{\"id\":1,\"stuff\":[{\"name\":\"first\"}]}]", json); } + public void testIssue809_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();