Skip to content

Commit 5d3a256

Browse files
author
Jonathan Haber
authored
More customizable TokenFilter inclusion (#573)
* Add support for writing empty objects and arrays * Get it working * Add some more tests * Switch to enum * Rename enum * Rename arg * Improve comment * Fix indentation * Rename constant * Rename to TokenFilterInclusion * Move enum to TokenFilter * Apply to parser as well * Add tests * Put back star imports * More star imports
1 parent c04e924 commit 5d3a256

File tree

10 files changed

+542
-203
lines changed

10 files changed

+542
-203
lines changed

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

Lines changed: 56 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import java.math.BigInteger;
88

99
import com.fasterxml.jackson.core.*;
10+
import com.fasterxml.jackson.core.filter.TokenFilter.Inclusion;
1011
import com.fasterxml.jackson.core.util.JsonGeneratorDelegate;
1112

1213
/**
@@ -18,6 +19,7 @@
1819
*/
1920
public class FilteringGeneratorDelegate extends JsonGeneratorDelegate
2021
{
22+
2123
/*
2224
/**********************************************************
2325
/* Configuration
@@ -45,18 +47,7 @@ public class FilteringGeneratorDelegate extends JsonGeneratorDelegate
4547
* done and only explicitly included entries are output; if `true` then
4648
* path from main level down to match is also included as necessary.
4749
*/
48-
protected boolean _includePath;
49-
50-
/* NOTE: this feature is included in the first version (2.6), but
51-
* there is no public API to enable it, yet, since there isn't an
52-
* actual use case. But it seemed possible need could arise, which
53-
* is feature has not yet been removed. If no use is found within
54-
* first version or two, just remove.
55-
*
56-
* Marked as deprecated since its status is uncertain.
57-
*/
58-
@Deprecated
59-
protected boolean _includeImmediateParent;
50+
protected TokenFilter.Inclusion _inclusion;
6051

6152
/*
6253
/**********************************************************
@@ -90,16 +81,23 @@ public class FilteringGeneratorDelegate extends JsonGeneratorDelegate
9081
/**********************************************************
9182
*/
9283

84+
@Deprecated
9385
public FilteringGeneratorDelegate(JsonGenerator d, TokenFilter f,
9486
boolean includePath, boolean allowMultipleMatches)
87+
{
88+
this(d, f, includePath ? Inclusion.INCLUDE_ALL_AND_PATH : Inclusion.ONLY_INCLUDE_ALL, allowMultipleMatches);
89+
}
90+
91+
public FilteringGeneratorDelegate(JsonGenerator d, TokenFilter f,
92+
TokenFilter.Inclusion inclusion, boolean allowMultipleMatches)
9593
{
9694
// By default, do NOT delegate copy methods
9795
super(d, false);
9896
rootFilter = f;
9997
// and this is the currently active filter for root values
10098
_itemFilter = f;
10199
_filterContext = TokenFilterContext.createRootContext(f);
102-
_includePath = includePath;
100+
_inclusion = inclusion;
103101
_allowMultipleMatches = allowMultipleMatches;
104102
}
105103

@@ -170,6 +168,10 @@ public void writeStartArray() throws IOException
170168
_checkParentPath();
171169
_filterContext = _filterContext.createChildArrayContext(_itemFilter, true);
172170
delegate.writeStartArray();
171+
} else if (_itemFilter != null && _inclusion == Inclusion.INCLUDE_NON_NULL) {
172+
_checkParentPath(false /* isMatch */);
173+
_filterContext = _filterContext.createChildArrayContext(_itemFilter, true);
174+
delegate.writeStartArray();
173175
} else {
174176
_filterContext = _filterContext.createChildArrayContext(_itemFilter, false);
175177
}
@@ -200,6 +202,10 @@ public void writeStartArray(int size) throws IOException
200202
_checkParentPath();
201203
_filterContext = _filterContext.createChildArrayContext(_itemFilter, true);
202204
delegate.writeStartArray(size);
205+
} else if (_itemFilter != null && _inclusion == Inclusion.INCLUDE_NON_NULL) {
206+
_checkParentPath(false /* isMatch */);
207+
_filterContext = _filterContext.createChildArrayContext(_itemFilter, true);
208+
delegate.writeStartArray(size);
203209
} else {
204210
_filterContext = _filterContext.createChildArrayContext(_itemFilter, false);
205211
}
@@ -298,6 +304,10 @@ public void writeStartObject() throws IOException
298304
_checkParentPath();
299305
_filterContext = _filterContext.createChildObjectContext(f, true);
300306
delegate.writeStartObject();
307+
} else if (f != null && _inclusion == Inclusion.INCLUDE_NON_NULL) {
308+
_checkParentPath(false /* isMatch */);
309+
_filterContext = _filterContext.createChildObjectContext(f, true);
310+
delegate.writeStartObject();
301311
} else { // filter out
302312
_filterContext = _filterContext.createChildObjectContext(f, false);
303313
}
@@ -328,6 +338,10 @@ public void writeStartObject(Object forValue) throws IOException
328338
_checkParentPath();
329339
_filterContext = _filterContext.createChildObjectContext(f, true);
330340
delegate.writeStartObject(forValue);
341+
} else if (f != null && _inclusion == Inclusion.INCLUDE_NON_NULL) {
342+
_checkParentPath(false /* isMatch */);
343+
_filterContext = _filterContext.createChildObjectContext(f, true);
344+
delegate.writeStartObject(forValue);
331345
} else { // filter out
332346
_filterContext = _filterContext.createChildObjectContext(f, false);
333347
}
@@ -441,7 +455,7 @@ public void writeString(String value) throws IOException
441455
}
442456
}
443457
_checkParentPath();
444-
}
458+
}
445459
delegate.writeString(value);
446460
}
447461

@@ -463,7 +477,7 @@ public void writeString(char[] text, int offset, int len) throws IOException
463477
}
464478
}
465479
_checkParentPath();
466-
}
480+
}
467481
delegate.writeString(text, offset, len);
468482
}
469483

@@ -484,7 +498,7 @@ public void writeString(SerializableString value) throws IOException
484498
}
485499
}
486500
_checkParentPath();
487-
}
501+
}
488502
delegate.writeString(value);
489503
}
490504

@@ -637,7 +651,7 @@ public void writeNumber(short v) throws IOException
637651
}
638652
}
639653
_checkParentPath();
640-
}
654+
}
641655
delegate.writeNumber(v);
642656
}
643657

@@ -658,7 +672,7 @@ public void writeNumber(int v) throws IOException
658672
}
659673
}
660674
_checkParentPath();
661-
}
675+
}
662676
delegate.writeNumber(v);
663677
}
664678

@@ -679,7 +693,7 @@ public void writeNumber(long v) throws IOException
679693
}
680694
}
681695
_checkParentPath();
682-
}
696+
}
683697
delegate.writeNumber(v);
684698
}
685699

@@ -700,7 +714,7 @@ public void writeNumber(BigInteger v) throws IOException
700714
}
701715
}
702716
_checkParentPath();
703-
}
717+
}
704718
delegate.writeNumber(v);
705719
}
706720

@@ -721,7 +735,7 @@ public void writeNumber(double v) throws IOException
721735
}
722736
}
723737
_checkParentPath();
724-
}
738+
}
725739
delegate.writeNumber(v);
726740
}
727741

@@ -742,7 +756,7 @@ public void writeNumber(float v) throws IOException
742756
}
743757
}
744758
_checkParentPath();
745-
}
759+
}
746760
delegate.writeNumber(v);
747761
}
748762

@@ -763,7 +777,7 @@ public void writeNumber(BigDecimal v) throws IOException
763777
}
764778
}
765779
_checkParentPath();
766-
}
780+
}
767781
delegate.writeNumber(v);
768782
}
769783

@@ -826,7 +840,7 @@ public void writeBoolean(boolean v) throws IOException
826840
}
827841
}
828842
_checkParentPath();
829-
}
843+
}
830844
delegate.writeBoolean(v);
831845
}
832846

@@ -847,7 +861,7 @@ public void writeNull() throws IOException
847861
}
848862
}
849863
_checkParentPath();
850-
}
864+
}
851865
delegate.writeNull();
852866
}
853867

@@ -970,13 +984,23 @@ public void copyCurrentStructure(JsonParser jp) throws IOException {
970984

971985
protected void _checkParentPath() throws IOException
972986
{
973-
++_matchCount;
987+
_checkParentPath(true);
988+
}
989+
990+
protected void _checkParentPath(boolean isMatch) throws IOException
991+
{
992+
if (isMatch) {
993+
++_matchCount;
994+
}
974995
// only need to construct path if parent wasn't written
975-
if (_includePath) {
996+
if (_inclusion == Inclusion.INCLUDE_ALL_AND_PATH) {
976997
_filterContext.writePath(delegate);
998+
} else if (_inclusion == Inclusion.INCLUDE_NON_NULL) {
999+
// path has already been written, except for maybe field name
1000+
_filterContext.ensureFieldNameWritten(delegate);
9771001
}
9781002
// also: if no multiple matches desired, short-cut checks
979-
if (!_allowMultipleMatches) {
1003+
if (isMatch && !_allowMultipleMatches) {
9801004
// Mark parents as "skip" so that further check calls are not made
9811005
_filterContext.skipParentChecks();
9821006
}
@@ -990,12 +1014,11 @@ protected void _checkParentPath() throws IOException
9901014
protected void _checkPropertyParentPath() throws IOException
9911015
{
9921016
++_matchCount;
993-
if (_includePath) {
1017+
if (_inclusion == Inclusion.INCLUDE_ALL_AND_PATH) {
9941018
_filterContext.writePath(delegate);
995-
} else if (_includeImmediateParent) {
996-
// 21-Apr-2015, tatu: Note that there is no API to enable this currently...
997-
// retained for speculative future use
998-
_filterContext.writeImmediatePath(delegate);
1019+
} else if (_inclusion == Inclusion.INCLUDE_NON_NULL) {
1020+
// path has already been written, except for maybe field name
1021+
_filterContext.ensureFieldNameWritten(delegate);
9991022
}
10001023

10011024
// also: if no multiple matches desired, short-cut checks

0 commit comments

Comments
 (0)