Skip to content

Commit 6feec20

Browse files
committed
Fix #208: FilteringParserDelegate match count support
1 parent 74564bf commit 6feec20

File tree

3 files changed

+124
-31
lines changed

3 files changed

+124
-31
lines changed

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

+21-7
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,7 @@ public JsonToken nextToken() throws IOException
414414
}
415415
_itemFilter = f;
416416
if (f == TokenFilter.INCLUDE_ALL) {
417-
if (_includePath) {
417+
if (_verifyAllowedMatches() && _includePath) {
418418
return (_currToken = t);
419419
}
420420
}
@@ -437,7 +437,9 @@ public JsonToken nextToken() throws IOException
437437
f = _headContext.checkValue(f);
438438
if ((f == TokenFilter.INCLUDE_ALL)
439439
|| ((f != null) && f.includeValue(delegate))) {
440-
return (_currToken = t);
440+
if (_verifyAllowedMatches()) {
441+
return (_currToken = t);
442+
}
441443
}
442444
}
443445
// Otherwise not included (leaves must be explicitly included)
@@ -572,7 +574,7 @@ protected final JsonToken _nextToken2() throws IOException
572574
}
573575
_itemFilter = f;
574576
if (f == TokenFilter.INCLUDE_ALL) {
575-
if (_includePath) {
577+
if (_verifyAllowedMatches() && _includePath) {
576578
return (_currToken = t);
577579
}
578580
// if (_includeImmediateParent) { ...
@@ -597,7 +599,9 @@ protected final JsonToken _nextToken2() throws IOException
597599
f = _headContext.checkValue(f);
598600
if ((f == TokenFilter.INCLUDE_ALL)
599601
|| ((f != null) && f.includeValue(delegate))) {
600-
return (_currToken = t);
602+
if (_verifyAllowedMatches()) {
603+
return (_currToken = t);
604+
}
601605
}
602606
}
603607
// Otherwise not included (leaves must be explicitly included)
@@ -714,7 +718,7 @@ protected final JsonToken _nextTokenWithBuffering(final TokenFilterContext buffR
714718
continue main_loop;
715719
}
716720
_itemFilter = f;
717-
if (f == TokenFilter.INCLUDE_ALL) {
721+
if (f == TokenFilter.INCLUDE_ALL && _verifyAllowedMatches()) {
718722
return _nextBuffered(buffRoot);
719723
}
720724
}
@@ -729,7 +733,9 @@ protected final JsonToken _nextTokenWithBuffering(final TokenFilterContext buffR
729733
f = _headContext.checkValue(f);
730734
if ((f == TokenFilter.INCLUDE_ALL)
731735
|| ((f != null) && f.includeValue(delegate))) {
732-
return _nextBuffered(buffRoot);
736+
if (_verifyAllowedMatches()) {
737+
return _nextBuffered(buffRoot);
738+
}
733739
}
734740
}
735741
// Otherwise not included (leaves must be explicitly included)
@@ -767,7 +773,15 @@ private JsonToken _nextBuffered(TokenFilterContext buffRoot) throws IOException
767773
}
768774
}
769775
}
770-
776+
777+
private final boolean _verifyAllowedMatches() throws IOException {
778+
if (_matchCount == 0 || _allowMultipleMatches) {
779+
++_matchCount;
780+
return true;
781+
}
782+
return false;
783+
}
784+
771785
@Override
772786
public JsonToken nextValue() throws IOException {
773787
// 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,104 +81,176 @@ 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

184256
@SuppressWarnings("resource")

0 commit comments

Comments
 (0)