Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow all array elements in JsonPointerBasedFilter #1036

Merged
merged 2 commits into from
May 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions release-notes/CREDITS-2.x
Original file line number Diff line number Diff line change
Expand Up @@ -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)
2 changes: 2 additions & 0 deletions release-notes/VERSION-2.x
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 <code>ptrExpr</code> 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
Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -26,7 +27,7 @@ private OrTokenFilter(final List<? extends TokenFilter> delegates) {
}

static OrTokenFilter create(final Set<String> 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
Expand Down Expand Up @@ -69,7 +70,7 @@ private TokenFilter executeDelegates(final UnaryOperator<TokenFilter> operator)
}
}

public void testIssue809_singleProperty() throws Exception
public void testIssue890_singleProperty() throws Exception
{
// GIVEN
final Set<String> jsonPointers = Stream.of("/0/id").collect(Collectors.toSet());
Expand All @@ -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<String> jsonPointers = Stream.of("/0/id", "/0/stuff/0/name").collect(Collectors.toSet());
Expand All @@ -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<String> 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();
Expand Down