Skip to content

Commit 1c0ba97

Browse files
committed
FasterXML#208 FilteringParserDelegate match count support
1 parent 09298ed commit 1c0ba97

File tree

3 files changed

+128
-35
lines changed

3 files changed

+128
-35
lines changed

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

+25-11
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ public JsonToken nextToken() throws IOException
233233
// Check for _allowMultipleMatches - false and at least there is one token - which is _currToken
234234
// check for no buffered context _exposedContext - null
235235
// If all the conditions matches then check for scalar / non-scalar property
236-
236+
237237
if (!_allowMultipleMatches && (_currToken != null) && (_exposedContext == null)) {
238238
// if not scalar and ended successfully, then return null
239239
if ((_currToken.isStructEnd() && _headContext.isStartHandled()) ){
@@ -378,7 +378,7 @@ public JsonToken nextToken() throws IOException
378378
boolean returnEnd = _headContext.isStartHandled();
379379
f = _headContext.getFilter();
380380
if ((f != null) && (f != TokenFilter.INCLUDE_ALL)) {
381-
f.filterFinishArray();
381+
f.filterFinishObject();
382382
}
383383
_headContext = _headContext.getParent();
384384
_itemFilter = _headContext.getFilter();
@@ -418,7 +418,7 @@ public JsonToken nextToken() throws IOException
418418
}
419419
_itemFilter = f;
420420
if (f == TokenFilter.INCLUDE_ALL) {
421-
if (_includePath) {
421+
if (_verifyAllowedMatches() && _includePath) {
422422
return (_currToken = t);
423423
}
424424
}
@@ -441,7 +441,9 @@ public JsonToken nextToken() throws IOException
441441
f = _headContext.checkValue(f);
442442
if ((f == TokenFilter.INCLUDE_ALL)
443443
|| ((f != null) && f.includeValue(delegate))) {
444-
return (_currToken = t);
444+
if (_verifyAllowedMatches()) {
445+
return (_currToken = t);
446+
}
445447
}
446448
}
447449
// Otherwise not included (leaves must be explicitly included)
@@ -545,7 +547,7 @@ protected final JsonToken _nextToken2() throws IOException
545547
boolean returnEnd = _headContext.isStartHandled();
546548
f = _headContext.getFilter();
547549
if ((f != null) && (f != TokenFilter.INCLUDE_ALL)) {
548-
f.filterFinishArray();
550+
f.filterFinishObject();
549551
}
550552
_headContext = _headContext.getParent();
551553
_itemFilter = _headContext.getFilter();
@@ -576,7 +578,7 @@ protected final JsonToken _nextToken2() throws IOException
576578
}
577579
_itemFilter = f;
578580
if (f == TokenFilter.INCLUDE_ALL) {
579-
if (_includePath) {
581+
if (_verifyAllowedMatches() && _includePath) {
580582
return (_currToken = t);
581583
}
582584
// if (_includeImmediateParent) { ...
@@ -601,7 +603,9 @@ protected final JsonToken _nextToken2() throws IOException
601603
f = _headContext.checkValue(f);
602604
if ((f == TokenFilter.INCLUDE_ALL)
603605
|| ((f != null) && f.includeValue(delegate))) {
604-
return (_currToken = t);
606+
if (_verifyAllowedMatches()) {
607+
return (_currToken = t);
608+
}
605609
}
606610
}
607611
// Otherwise not included (leaves must be explicitly included)
@@ -680,7 +684,7 @@ protected final JsonToken _nextTokenWithBuffering(final TokenFilterContext buffR
680684
// included (won't get this far otherwise)
681685
f = _headContext.getFilter();
682686
if ((f != null) && (f != TokenFilter.INCLUDE_ALL)) {
683-
f.filterFinishArray();
687+
f.filterFinishObject();
684688
}
685689
boolean gotEnd = (_headContext == buffRoot);
686690
boolean returnEnd = gotEnd && _headContext.isStartHandled();
@@ -718,7 +722,7 @@ protected final JsonToken _nextTokenWithBuffering(final TokenFilterContext buffR
718722
continue main_loop;
719723
}
720724
_itemFilter = f;
721-
if (f == TokenFilter.INCLUDE_ALL) {
725+
if (f == TokenFilter.INCLUDE_ALL && _verifyAllowedMatches()) {
722726
return _nextBuffered(buffRoot);
723727
}
724728
}
@@ -733,7 +737,9 @@ protected final JsonToken _nextTokenWithBuffering(final TokenFilterContext buffR
733737
f = _headContext.checkValue(f);
734738
if ((f == TokenFilter.INCLUDE_ALL)
735739
|| ((f != null) && f.includeValue(delegate))) {
736-
return _nextBuffered(buffRoot);
740+
if (_verifyAllowedMatches()) {
741+
return _nextBuffered(buffRoot);
742+
}
737743
}
738744
}
739745
// Otherwise not included (leaves must be explicitly included)
@@ -771,7 +777,15 @@ private JsonToken _nextBuffered(TokenFilterContext buffRoot) throws IOException
771777
}
772778
}
773779
}
774-
780+
781+
private final boolean _verifyAllowedMatches() throws IOException {
782+
if (_matchCount == 0 || _allowMultipleMatches) {
783+
++_matchCount;
784+
return true;
785+
}
786+
return false;
787+
}
788+
775789
@Override
776790
public JsonToken nextValue() throws IOException {
777791
// Re-implemented same as ParserMinimalBase:

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

+15-8
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ public void testSingleMatchFilteringWithPathAlternate1() throws Exception
190190
gen.close();
191191

192192
assertEquals(aposToQuotes("{'ob':{'value':['x']}}"), w.toString());
193+
assertEquals(1, gen.getMatchCount());
193194
}
194195

195196
public void testSingleMatchFilteringWithPathRawBinary() throws Exception
@@ -240,47 +241,51 @@ public void testSingleMatchFilteringWithPathRawBinary() throws Exception
240241
gen.close();
241242

242243
assertEquals(aposToQuotes("{'array':['AQ==',1,2,3,4 ,5.0 /*x*/,6.25,7.5]}"), w.toString());
244+
assertEquals(1, gen.getMatchCount());
243245
}
244246

245247
public void testMultipleMatchFilteringWithPath1() throws Exception
246248
{
247249
StringWriter w = new StringWriter();
248-
JsonGenerator gen = new FilteringGeneratorDelegate(JSON_F.createGenerator(w),
250+
FilteringGeneratorDelegate gen = new FilteringGeneratorDelegate(JSON_F.createGenerator(w),
249251
new NameMatchFilter("value0", "value2"),
250252
true, /* includePath */ true /* multipleMatches */ );
251253
final String JSON = "{'a':123,'array':[1,2],'ob':{'value0':2,'value':3,'value2':4},'b':true}";
252254
writeJsonDoc(JSON_F, JSON, gen);
253255
assertEquals(aposToQuotes("{'ob':{'value0':2,'value2':4}}"), w.toString());
256+
assertEquals(2, gen.getMatchCount());
254257
}
255258

256259
public void testMultipleMatchFilteringWithPath2() throws Exception
257260
{
258261
StringWriter w = new StringWriter();
259-
260-
JsonGenerator gen = new FilteringGeneratorDelegate(JSON_F.createGenerator(w),
262+
263+
FilteringGeneratorDelegate gen = new FilteringGeneratorDelegate(JSON_F.createGenerator(w),
261264
new NameMatchFilter("array", "b", "value"),
262265
true, true);
263266
final String JSON = "{'a':123,'array':[1,2],'ob':{'value0':2,'value':3,'value2':4},'b':true}";
264267
writeJsonDoc(JSON_F, JSON, gen);
265268
assertEquals(aposToQuotes("{'array':[1,2],'ob':{'value':3},'b':true}"), w.toString());
269+
assertEquals(3, gen.getMatchCount());
266270
}
267271

268272
public void testMultipleMatchFilteringWithPath3() throws Exception
269273
{
270274
StringWriter w = new StringWriter();
271-
272-
JsonGenerator gen = new FilteringGeneratorDelegate(JSON_F.createGenerator(w),
275+
276+
FilteringGeneratorDelegate gen = new FilteringGeneratorDelegate(JSON_F.createGenerator(w),
273277
new NameMatchFilter("value"),
274278
true, true);
275279
final String JSON = "{'root':{'a0':true,'a':{'value':3},'b':{'value':4}},'b0':false}";
276280
writeJsonDoc(JSON_F, JSON, gen);
277281
assertEquals(aposToQuotes("{'root':{'a':{'value':3},'b':{'value':4}}}"), w.toString());
282+
assertEquals(2, gen.getMatchCount());
278283
}
279284

280285
public void testIndexMatchWithPath1() throws Exception
281286
{
282287
StringWriter w = new StringWriter();
283-
JsonGenerator gen = new FilteringGeneratorDelegate(JSON_F.createGenerator(w),
288+
FilteringGeneratorDelegate gen = new FilteringGeneratorDelegate(JSON_F.createGenerator(w),
284289
new IndexMatchFilter(1),
285290
true, true);
286291
final String JSON = "{'a':123,'array':[1,2],'ob':{'value0':2,'value':3,'value2':4},'b':true}";
@@ -293,24 +298,26 @@ public void testIndexMatchWithPath1() throws Exception
293298
true, true);
294299
writeJsonDoc(JSON_F, JSON, gen);
295300
assertEquals(aposToQuotes("{'array':[1]}"), w.toString());
301+
assertEquals(1, gen.getMatchCount());
296302
}
297303

298304
public void testIndexMatchWithPath2() throws Exception
299305
{
300306
StringWriter w = new StringWriter();
301-
JsonGenerator gen = new FilteringGeneratorDelegate(JSON_F.createGenerator(w),
307+
FilteringGeneratorDelegate gen = new FilteringGeneratorDelegate(JSON_F.createGenerator(w),
302308
new IndexMatchFilter(0,1),
303309
true, true);
304310
final String JSON = "{'a':123,'array':[1,2],'ob':{'value0':2,'value':3,'value2':4},'b':true}";
305311
writeJsonDoc(JSON_F, JSON, gen);
306312
assertEquals(aposToQuotes("{'array':[1,2]}"), w.toString());
313+
assertEquals(2, gen.getMatchCount());
307314
}
308315

309316
public void testWriteStartObjectWithObject() throws Exception
310317
{
311318
StringWriter w = new StringWriter();
312319

313-
JsonGenerator gen = new FilteringGeneratorDelegate(JSON_F.createGenerator(w),
320+
FilteringGeneratorDelegate gen = new FilteringGeneratorDelegate(JSON_F.createGenerator(w),
314321
TokenFilter.INCLUDE_ALL,
315322
true, true);
316323

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

+88-16
Original file line numberDiff line numberDiff line change
@@ -81,103 +81,175 @@ public void testNonFiltering() throws Exception
8181
public void testSingleMatchFilteringWithoutPath() throws Exception
8282
{
8383
JsonParser p0 = JSON_F.createParser(SIMPLE);
84-
JsonParser p = new FilteringParserDelegate(p0,
84+
FilteringParserDelegate p = new FilteringParserDelegate(p0,
8585
new NameMatchFilter("value"),
8686
false, // includePath
8787
false // multipleMatches
8888
);
8989
String result = readAndWrite(JSON_F, p);
9090
assertEquals(aposToQuotes("3"), result);
91+
assertEquals(1, p.getMatchCount());
92+
}
93+
94+
public void testSingleMatchFilteringWithPath() throws Exception
95+
{
96+
String jsonString = aposToQuotes("{'a':123,'array':[1,2],'ob':{'value0':2,'value':3,'value2':4},'b':true}");
97+
JsonParser p0 = JSON_F.createParser(jsonString);
98+
FilteringParserDelegate p = new FilteringParserDelegate(p0,
99+
new NameMatchFilter("a"),
100+
true, // includePath
101+
false // multipleMatches
102+
);
103+
String result = readAndWrite(JSON_F, p);
104+
assertEquals(aposToQuotes("{'a':123}"), result);
105+
assertEquals(1, p.getMatchCount());
91106
}
92107

93108
@SuppressWarnings("resource")
94-
public void testNotAllowMultipleMatches() throws Exception
109+
public void testNotAllowMultipleMatchesWithoutPath1() throws Exception
95110
{
96-
String jsonString = aposToQuotes("{'a':123,'array':[1,2],'ob':{'value0':2,'value':3,'value2':4},'value':4,'b':true}");
111+
String jsonString = aposToQuotes("{'a':123,'array':[1,2],'ob':{'value0':2,'value':3,'value2':4,'value':{'value0':2}},'b':true}");
97112
JsonParser p0 = JSON_F.createParser(jsonString);
98-
JsonParser p = new FilteringParserDelegate(p0,
113+
FilteringParserDelegate p = new FilteringParserDelegate(p0,
99114
new NameMatchFilter("value"),
100115
false, // includePath
101116
false // multipleMatches -false
102117
);
103118
String result = readAndWrite(JSON_F, p);
104119
assertEquals(aposToQuotes("3"), result);
120+
assertEquals(1, p.getMatchCount());
105121
}
106-
122+
107123
@SuppressWarnings("resource")
108-
public void testAllowMultipleMatches() throws Exception
124+
public void testNotAllowMultipleMatchesWithoutPath2() throws Exception
109125
{
110-
String jsonString = aposToQuotes("{'a':123,'array':[1,2],'ob':{'value0':2,'value':3,'value2':4},'value':4,'b':true}");
126+
String jsonString = aposToQuotes("{'a':123,'array':[1,2],'array':[3,4],'ob':{'value0':2,'value':3,'value2':4,'value':{'value0':2}},'value':\"val\",'b':true}");
111127
JsonParser p0 = JSON_F.createParser(jsonString);
112-
JsonParser p = new FilteringParserDelegate(p0,
128+
FilteringParserDelegate p = new FilteringParserDelegate(p0,
129+
new IndexMatchFilter(1),
130+
false, // includePath
131+
false // multipleMatches -false
132+
);
133+
String result = readAndWrite(JSON_F, p);
134+
assertEquals(aposToQuotes("2"), result);
135+
assertEquals(1, p.getMatchCount());
136+
}
137+
138+
@SuppressWarnings("resource")
139+
public void testAllowMultipleMatchesWithoutPath() throws Exception
140+
{
141+
String jsonString = aposToQuotes("{'a':123,'array':[1,2],'ob':{'value0':2,'value':3,'value2':4,'value':{'value0':2}},'value':\"val\",'b':true}");
142+
JsonParser p0 = JSON_F.createParser(jsonString);
143+
FilteringParserDelegate p = new FilteringParserDelegate(p0,
113144
new NameMatchFilter("value"),
114145
false, // includePath
115146
true // multipleMatches - true
116147
);
117148
String result = readAndWrite(JSON_F, p);
118-
assertEquals(aposToQuotes("3 4"), result);
149+
assertEquals(aposToQuotes("3 {\"value0\":2} \"val\""), result);
150+
assertEquals(3, p.getMatchCount());
151+
}
152+
153+
154+
@SuppressWarnings("resource")
155+
public void testAllowMultipleMatchesWithPath1() throws Exception
156+
{
157+
String jsonString = aposToQuotes("{'a':123,'array':[1,2],'ob':{'value0':2,'value':3,'value2':4,'value':{'value0':2}},'value':\"val\",'b':true}");
158+
JsonParser p0 = JSON_F.createParser(jsonString);
159+
FilteringParserDelegate p = new FilteringParserDelegate(p0,
160+
new NameMatchFilter("value"),
161+
true, // includePath
162+
true // multipleMatches - true
163+
);
164+
String result = readAndWrite(JSON_F, p);
165+
assertEquals(aposToQuotes("{\"ob\":{\"value\":3,\"value\":{\"value0\":2}},\"value\":\"val\"}"), result);
166+
assertEquals(3, p.getMatchCount());
167+
}
168+
169+
170+
@SuppressWarnings("resource")
171+
public void testAllowMultipleMatchesWithPath2() throws Exception
172+
{
173+
String jsonString = aposToQuotes("{'a':123,'array':[1,2],'ob':{'value0':2,'value':3,'array':[3,4],'value':{'value0':2}},'value':\"val\",'b':true}");
174+
JsonParser p0 = JSON_F.createParser(jsonString);
175+
FilteringParserDelegate p = new FilteringParserDelegate(p0,
176+
new IndexMatchFilter(1),
177+
true, // includePath
178+
true // multipleMatches - true
179+
);
180+
String result = readAndWrite(JSON_F, p);
181+
assertEquals(aposToQuotes("{\"array\":[2],\"ob\":{\"array\":[4]}}"), result);
182+
assertEquals(2, p.getMatchCount());
119183
}
120184

121185
@SuppressWarnings("resource")
122186
public void testMultipleMatchFilteringWithPath1() throws Exception
123187
{
124188
JsonParser p0 = JSON_F.createParser(SIMPLE);
125-
JsonParser p = new FilteringParserDelegate(p0,
189+
FilteringParserDelegate p = new FilteringParserDelegate(p0,
126190
new NameMatchFilter("value0", "value2"),
127191
true, /* includePath */ true /* multipleMatches */ );
128192
String result = readAndWrite(JSON_F, p);
129193
assertEquals(aposToQuotes("{'ob':{'value0':2,'value2':4}}"), result);
194+
assertEquals(2, p.getMatchCount());
195+
130196
}
131197

132198
@SuppressWarnings("resource")
133199
public void testMultipleMatchFilteringWithPath2() throws Exception
134200
{
135201
String INPUT = aposToQuotes("{'a':123,'ob':{'value0':2,'value':3,'value2':4},'b':true}");
136202
JsonParser p0 = JSON_F.createParser(INPUT);
137-
JsonParser p = new FilteringParserDelegate(p0,
203+
FilteringParserDelegate p = new FilteringParserDelegate(p0,
138204
new NameMatchFilter("b", "value"),
139205
true, true);
140206

141207
String result = readAndWrite(JSON_F, p);
142208
assertEquals(aposToQuotes("{'ob':{'value':3},'b':true}"), result);
209+
assertEquals(2, p.getMatchCount());
143210
}
144211

145212
@SuppressWarnings("resource")
146213
public void testMultipleMatchFilteringWithPath3() throws Exception
147214
{
148-
final String JSON = aposToQuotes("{'root':{'a0':true,'a':{'value':3},'b':{'value':4}},'b0':false}");
215+
final String JSON = aposToQuotes("{'root':{'a0':true,'a':{'value':3},'b':{'value':\"foo\"}},'b0':false}");
149216
JsonParser p0 = JSON_F.createParser(JSON);
150-
JsonParser p = new FilteringParserDelegate(p0,
217+
FilteringParserDelegate p = new FilteringParserDelegate(p0,
151218
new NameMatchFilter("value"),
152219
true, true);
153220
String result = readAndWrite(JSON_F, p);
154-
assertEquals(aposToQuotes("{'root':{'a':{'value':3},'b':{'value':4}}}"), result);
221+
assertEquals(aposToQuotes("{'root':{'a':{'value':3},'b':{'value':\"foo\"}}}"), result);
222+
assertEquals(2, p.getMatchCount());
155223
}
156224

157225
@SuppressWarnings("resource")
158226
public void testIndexMatchWithPath1() throws Exception
159227
{
160-
JsonParser p = new FilteringParserDelegate(JSON_F.createParser(SIMPLE),
228+
FilteringParserDelegate p = new FilteringParserDelegate(JSON_F.createParser(SIMPLE),
161229
new IndexMatchFilter(1), true, true);
162230
String result = readAndWrite(JSON_F, p);
163231
assertEquals(aposToQuotes("{'array':[2]}"), result);
232+
assertEquals(1, p.getMatchCount());
164233

165234
p = new FilteringParserDelegate(JSON_F.createParser(SIMPLE),
166235
new IndexMatchFilter(0), true, true);
167236
result = readAndWrite(JSON_F, p);
168237
assertEquals(aposToQuotes("{'array':[1]}"), result);
238+
assertEquals(1, p.getMatchCount());
169239
}
170240

171241
@SuppressWarnings("resource")
172242
public void testIndexMatchWithPath2() throws Exception
173243
{
174-
JsonParser p = new FilteringParserDelegate(JSON_F.createParser(SIMPLE),
244+
FilteringParserDelegate p = new FilteringParserDelegate(JSON_F.createParser(SIMPLE),
175245
new IndexMatchFilter(0, 1), true, true);
176246
assertEquals(aposToQuotes("{'array':[1,2]}"), readAndWrite(JSON_F, p));
247+
assertEquals(2, p.getMatchCount());
177248

178249
String JSON = aposToQuotes("{'a':123,'array':[1,2,3,4,5],'b':[1,2,3]}");
179250
p = new FilteringParserDelegate(JSON_F.createParser(JSON),
180251
new IndexMatchFilter(1, 3), true, true);
181252
assertEquals(aposToQuotes("{'array':[2,4],'b':[2]}"), readAndWrite(JSON_F, p));
253+
assertEquals(3, p.getMatchCount());
182254
}
183255
}

0 commit comments

Comments
 (0)