Merge pull request #16017 from beiske/xcontent_exclude

Add option to exclude based on paths in XContent
This commit is contained in:
Konrad Beiske 2016-02-03 13:51:49 +01:00
commit 2c247e9d56
14 changed files with 994 additions and 177 deletions

View File

@ -41,13 +41,28 @@ public interface XContent {
/** /**
* Creates a new generator using the provided output stream. * Creates a new generator using the provided output stream.
*/ */
XContentGenerator createGenerator(OutputStream os) throws IOException; default XContentGenerator createGenerator(OutputStream os) throws IOException {
return createGenerator(os, null, true);
}
/** /**
* Creates a new generator using the provided output stream and some filters. * Creates a new generator using the provided output stream and some
* inclusive filters. Same as createGenerator(os, filters, true).
*/ */
XContentGenerator createGenerator(OutputStream os, String[] filters) throws IOException; default XContentGenerator createGenerator(OutputStream os, String[] filters) throws IOException {
return createGenerator(os, filters, true);
}
/**
* Creates a new generator using the provided output stream and some
* filters.
*
* @param inclusive
* If true only paths matching a filter will be included in
* output. If false no path matching a filter will be included in
* output
*/
XContentGenerator createGenerator(OutputStream os, String[] filters, boolean inclusive) throws IOException;
/** /**
* Creates a parser over the provided string content. * Creates a parser over the provided string content.
*/ */
@ -77,4 +92,5 @@ public interface XContent {
* Creates a parser over the provided reader. * Creates a parser over the provided reader.
*/ */
XContentParser createParser(Reader reader) throws IOException; XContentParser createParser(Reader reader) throws IOException;
} }

View File

@ -83,6 +83,10 @@ public final class XContentBuilder implements BytesStream, Releasable {
return new XContentBuilder(xContent, new BytesStreamOutput(), filters); return new XContentBuilder(xContent, new BytesStreamOutput(), filters);
} }
public static XContentBuilder builder(XContent xContent, String[] filters, boolean inclusive) throws IOException {
return new XContentBuilder(xContent, new BytesStreamOutput(), filters, inclusive);
}
private XContentGenerator generator; private XContentGenerator generator;
private final OutputStream bos; private final OutputStream bos;
@ -102,13 +106,25 @@ public final class XContentBuilder implements BytesStream, Releasable {
} }
/** /**
* Constructs a new builder using the provided xcontent, an OutputStream and some filters. The * Constructs a new builder using the provided xcontent, an OutputStream and
* filters are used to filter fields that won't be written to the OutputStream. Make sure * some filters. If filters are specified, only those values matching a
* to call {@link #close()} when the builder is done with. * filter will be written to the output stream. Make sure to call
* {@link #close()} when the builder is done with.
*/ */
public XContentBuilder(XContent xContent, OutputStream bos, String[] filters) throws IOException { public XContentBuilder(XContent xContent, OutputStream bos, String[] filters) throws IOException {
this(xContent, bos, filters, true);
}
/**
* Constructs a new builder using the provided xcontent, an OutputStream and
* some filters. If {@code filters} are specified and {@code inclusive} is
* true, only those values matching a filter will be written to the output
* stream. If {@code inclusive} is false, those matching will be excluded.
* Make sure to call {@link #close()} when the builder is done with.
*/
public XContentBuilder(XContent xContent, OutputStream bos, String[] filters, boolean inclusive) throws IOException {
this.bos = bos; this.bos = bos;
this.generator = xContent.createGenerator(bos, filters); this.generator = xContent.createGenerator(bos, filters, inclusive);
} }
public XContentBuilder fieldCaseConversion(FieldCaseConversion fieldCaseConversion) { public XContentBuilder fieldCaseConversion(FieldCaseConversion fieldCaseConversion) {

View File

@ -121,5 +121,6 @@ public interface XContentGenerator extends Closeable {
void flush() throws IOException; void flush() throws IOException;
@Override
void close() throws IOException; void close() throws IOException;
} }

View File

@ -67,13 +67,8 @@ public class CborXContent implements XContent {
} }
@Override @Override
public XContentGenerator createGenerator(OutputStream os) throws IOException { public XContentGenerator createGenerator(OutputStream os, String[] filters, boolean inclusive) throws IOException {
return new CborXContentGenerator(cborFactory.createGenerator(os, JsonEncoding.UTF8), os); return new CborXContentGenerator(cborFactory.createGenerator(os, JsonEncoding.UTF8), os, filters, inclusive);
}
@Override
public XContentGenerator createGenerator(OutputStream os, String[] filters) throws IOException {
return new CborXContentGenerator(cborFactory.createGenerator(os, JsonEncoding.UTF8), os, filters);
} }
@Override @Override
@ -108,4 +103,5 @@ public class CborXContent implements XContent {
public XContentParser createParser(Reader reader) throws IOException { public XContentParser createParser(Reader reader) throws IOException {
return new CborXContentParser(cborFactory.createParser(reader)); return new CborXContentParser(cborFactory.createParser(reader));
} }
} }

View File

@ -20,6 +20,7 @@
package org.elasticsearch.common.xcontent.cbor; package org.elasticsearch.common.xcontent.cbor;
import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonGenerator;
import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.common.xcontent.json.JsonXContentGenerator; import org.elasticsearch.common.xcontent.json.JsonXContentGenerator;
@ -31,7 +32,11 @@ import java.io.OutputStream;
public class CborXContentGenerator extends JsonXContentGenerator { public class CborXContentGenerator extends JsonXContentGenerator {
public CborXContentGenerator(JsonGenerator jsonGenerator, OutputStream os, String... filters) { public CborXContentGenerator(JsonGenerator jsonGenerator, OutputStream os, String... filters) {
super(jsonGenerator, os, filters); this(jsonGenerator, os, filters, true);
}
public CborXContentGenerator(JsonGenerator jsonGenerator, OutputStream os, String[] filters, boolean inclusive) {
super(jsonGenerator, os, filters, inclusive);
} }
@Override @Override

View File

@ -71,13 +71,8 @@ public class JsonXContent implements XContent {
} }
@Override @Override
public XContentGenerator createGenerator(OutputStream os) throws IOException { public XContentGenerator createGenerator(OutputStream os, String[] filters, boolean inclusive) throws IOException {
return new JsonXContentGenerator(jsonFactory.createGenerator(os, JsonEncoding.UTF8), os); return new JsonXContentGenerator(jsonFactory.createGenerator(os, JsonEncoding.UTF8), os, filters, inclusive);
}
@Override
public XContentGenerator createGenerator(OutputStream os, String[] filters) throws IOException {
return new JsonXContentGenerator(jsonFactory.createGenerator(os, JsonEncoding.UTF8), os, filters);
} }
@Override @Override

View File

@ -72,6 +72,10 @@ public class JsonXContentGenerator implements XContentGenerator {
private boolean prettyPrint = false; private boolean prettyPrint = false;
public JsonXContentGenerator(JsonGenerator jsonGenerator, OutputStream os, String... filters) { public JsonXContentGenerator(JsonGenerator jsonGenerator, OutputStream os, String... filters) {
this(jsonGenerator, os, filters, true);
}
public JsonXContentGenerator(JsonGenerator jsonGenerator, OutputStream os, String[] filters, boolean inclusive) {
if (jsonGenerator instanceof GeneratorBase) { if (jsonGenerator instanceof GeneratorBase) {
this.base = (GeneratorBase) jsonGenerator; this.base = (GeneratorBase) jsonGenerator;
} else { } else {
@ -82,7 +86,8 @@ public class JsonXContentGenerator implements XContentGenerator {
this.generator = jsonGenerator; this.generator = jsonGenerator;
this.filter = null; this.filter = null;
} else { } else {
this.filter = new FilteringGeneratorDelegate(jsonGenerator, new FilterPathBasedFilter(filters), true, true); this.filter = new FilteringGeneratorDelegate(jsonGenerator,
new FilterPathBasedFilter(filters, inclusive), true, true);
this.generator = this.filter; this.generator = this.filter;
} }
@ -375,6 +380,7 @@ public class JsonXContentGenerator implements XContentGenerator {
} }
} }
@Override
public final void writeRawValue(BytesReference content) throws IOException { public final void writeRawValue(BytesReference content) throws IOException {
XContentType contentType = XContentFactory.xContentType(content); XContentType contentType = XContentFactory.xContentType(content);
if (contentType == null) { if (contentType == null) {
@ -450,4 +456,5 @@ public class JsonXContentGenerator implements XContentGenerator {
} }
generator.close(); generator.close();
} }
} }

View File

@ -68,13 +68,8 @@ public class SmileXContent implements XContent {
} }
@Override @Override
public XContentGenerator createGenerator(OutputStream os) throws IOException { public XContentGenerator createGenerator(OutputStream os, String[] filters, boolean inclusive) throws IOException {
return new SmileXContentGenerator(smileFactory.createGenerator(os, JsonEncoding.UTF8), os); return new SmileXContentGenerator(smileFactory.createGenerator(os, JsonEncoding.UTF8), os, filters, inclusive);
}
@Override
public XContentGenerator createGenerator(OutputStream os, String[] filters) throws IOException {
return new SmileXContentGenerator(smileFactory.createGenerator(os, JsonEncoding.UTF8), os, filters);
} }
@Override @Override

View File

@ -20,6 +20,7 @@
package org.elasticsearch.common.xcontent.smile; package org.elasticsearch.common.xcontent.smile;
import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonGenerator;
import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.common.xcontent.json.JsonXContentGenerator; import org.elasticsearch.common.xcontent.json.JsonXContentGenerator;
@ -31,7 +32,11 @@ import java.io.OutputStream;
public class SmileXContentGenerator extends JsonXContentGenerator { public class SmileXContentGenerator extends JsonXContentGenerator {
public SmileXContentGenerator(JsonGenerator jsonGenerator, OutputStream os, String... filters) { public SmileXContentGenerator(JsonGenerator jsonGenerator, OutputStream os, String... filters) {
super(jsonGenerator, os, filters); this(jsonGenerator, os, filters, true);
}
public SmileXContentGenerator(JsonGenerator jsonGenerator, OutputStream os, String[] filters, boolean inclusive) {
super(jsonGenerator, os, filters, inclusive);
} }
@Override @Override

View File

@ -31,25 +31,30 @@ public class FilterPathBasedFilter extends TokenFilter {
* Marker value that should be used to indicate that a property name * Marker value that should be used to indicate that a property name
* or value matches one of the filter paths. * or value matches one of the filter paths.
*/ */
private static final TokenFilter MATCHING = new TokenFilter(){}; private static final TokenFilter MATCHING = new TokenFilter() {
};
/** /**
* Marker value that should be used to indicate that none of the * Marker value that should be used to indicate that none of the
* property names/values matches one of the filter paths. * property names/values matches one of the filter paths.
*/ */
private static final TokenFilter NO_MATCHING = new TokenFilter(){}; private static final TokenFilter NO_MATCHING = new TokenFilter() {
};
private final FilterPath[] filters; private final FilterPath[] filters;
public FilterPathBasedFilter(FilterPath[] filters) { private final boolean inclusive;
public FilterPathBasedFilter(FilterPath[] filters, boolean inclusive) {
if (CollectionUtils.isEmpty(filters)) { if (CollectionUtils.isEmpty(filters)) {
throw new IllegalArgumentException("filters cannot be null or empty"); throw new IllegalArgumentException("filters cannot be null or empty");
} }
this.inclusive = inclusive;
this.filters = filters; this.filters = filters;
} }
public FilterPathBasedFilter(String[] filters) { public FilterPathBasedFilter(String[] filters, boolean inclusive) {
this(FilterPath.compile(filters)); this(FilterPath.compile(filters), inclusive);
} }
/** /**
@ -77,31 +82,32 @@ public class FilterPathBasedFilter extends TokenFilter {
} }
if ((nextFilters != null) && (nextFilters.isEmpty() == false)) { if ((nextFilters != null) && (nextFilters.isEmpty() == false)) {
return new FilterPathBasedFilter(nextFilters.toArray(new FilterPath[nextFilters.size()])); return new FilterPathBasedFilter(nextFilters.toArray(new FilterPath[nextFilters.size()]), inclusive);
} }
} }
return NO_MATCHING; return NO_MATCHING;
} }
@Override @Override
public TokenFilter includeProperty(String name) { public TokenFilter includeProperty(String name) {
TokenFilter include = evaluate(name, filters); TokenFilter filter = evaluate(name, filters);
if (include == MATCHING) { if (filter == MATCHING) {
return TokenFilter.INCLUDE_ALL; return inclusive ? TokenFilter.INCLUDE_ALL : null;
} }
if (include == NO_MATCHING) { if (filter == NO_MATCHING) {
return null; return inclusive ? null : TokenFilter.INCLUDE_ALL;
} }
return include; return filter;
} }
@Override @Override
protected boolean _includeScalar() { protected boolean _includeScalar() {
for (FilterPath filter : filters) { for (FilterPath filter : filters) {
if (filter.matches()) { if (filter.matches()) {
return true; return inclusive;
} }
} }
return false; return !inclusive;
} }
} }

View File

@ -66,13 +66,8 @@ public class YamlXContent implements XContent {
} }
@Override @Override
public XContentGenerator createGenerator(OutputStream os) throws IOException { public XContentGenerator createGenerator(OutputStream os, String[] filters, boolean inclusive) throws IOException {
return new YamlXContentGenerator(yamlFactory.createGenerator(os, JsonEncoding.UTF8), os); return new YamlXContentGenerator(yamlFactory.createGenerator(os, JsonEncoding.UTF8), os, filters, inclusive);
}
@Override
public XContentGenerator createGenerator(OutputStream os, String[] filters) throws IOException {
return new YamlXContentGenerator(yamlFactory.createGenerator(os, JsonEncoding.UTF8), os, filters);
} }
@Override @Override

View File

@ -20,6 +20,7 @@
package org.elasticsearch.common.xcontent.yaml; package org.elasticsearch.common.xcontent.yaml;
import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonGenerator;
import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.common.xcontent.json.JsonXContentGenerator; import org.elasticsearch.common.xcontent.json.JsonXContentGenerator;
@ -31,7 +32,11 @@ import java.io.OutputStream;
public class YamlXContentGenerator extends JsonXContentGenerator { public class YamlXContentGenerator extends JsonXContentGenerator {
public YamlXContentGenerator(JsonGenerator jsonGenerator, OutputStream os, String... filters) { public YamlXContentGenerator(JsonGenerator jsonGenerator, OutputStream os, String... filters) {
super(jsonGenerator, os, filters); this(jsonGenerator, os, filters, true);
}
public YamlXContentGenerator(JsonGenerator jsonGenerator, OutputStream os, String[] filters, boolean inclusive) {
super(jsonGenerator, os, filters, inclusive);
} }
@Override @Override

View File

@ -31,59 +31,111 @@ public class FilterPathGeneratorFilteringTests extends ESTestCase {
private final JsonFactory JSON_FACTORY = new JsonFactory(); private final JsonFactory JSON_FACTORY = new JsonFactory();
public void testFilters() throws Exception { public void testInclusiveFilters() throws Exception {
final String SAMPLE = "{'a':0,'b':true,'c':'c_value','d':[0,1,2],'e':[{'f1':'f1_value','f2':'f2_value'},{'g1':'g1_value','g2':'g2_value'}],'h':{'i':{'j':{'k':{'l':'l_value'}}}}}"; final String SAMPLE = "{'a':0,'b':true,'c':'c_value','d':[0,1,2],'e':[{'f1':'f1_value','f2':'f2_value'},{'g1':'g1_value','g2':'g2_value'}],'h':{'i':{'j':{'k':{'l':'l_value'}}}}}";
assertResult(SAMPLE, "a", "{'a':0}"); assertResult(SAMPLE, "a", true, "{'a':0}");
assertResult(SAMPLE, "b", "{'b':true}"); assertResult(SAMPLE, "b", true, "{'b':true}");
assertResult(SAMPLE, "c", "{'c':'c_value'}"); assertResult(SAMPLE, "c", true, "{'c':'c_value'}");
assertResult(SAMPLE, "d", "{'d':[0,1,2]}"); assertResult(SAMPLE, "d", true, "{'d':[0,1,2]}");
assertResult(SAMPLE, "e", "{'e':[{'f1':'f1_value','f2':'f2_value'},{'g1':'g1_value','g2':'g2_value'}]}"); assertResult(SAMPLE, "e", true, "{'e':[{'f1':'f1_value','f2':'f2_value'},{'g1':'g1_value','g2':'g2_value'}]}");
assertResult(SAMPLE, "h", "{'h':{'i':{'j':{'k':{'l':'l_value'}}}}}"); assertResult(SAMPLE, "h", true, "{'h':{'i':{'j':{'k':{'l':'l_value'}}}}}");
assertResult(SAMPLE, "z", ""); assertResult(SAMPLE, "z", true, "");
assertResult(SAMPLE, "e.f1", "{'e':[{'f1':'f1_value'}]}"); assertResult(SAMPLE, "e.f1", true, "{'e':[{'f1':'f1_value'}]}");
assertResult(SAMPLE, "e.f2", "{'e':[{'f2':'f2_value'}]}"); assertResult(SAMPLE, "e.f2", true, "{'e':[{'f2':'f2_value'}]}");
assertResult(SAMPLE, "e.f*", "{'e':[{'f1':'f1_value','f2':'f2_value'}]}"); assertResult(SAMPLE, "e.f*", true, "{'e':[{'f1':'f1_value','f2':'f2_value'}]}");
assertResult(SAMPLE, "e.*2", "{'e':[{'f2':'f2_value'},{'g2':'g2_value'}]}"); assertResult(SAMPLE, "e.*2", true, "{'e':[{'f2':'f2_value'},{'g2':'g2_value'}]}");
assertResult(SAMPLE, "h.i", "{'h':{'i':{'j':{'k':{'l':'l_value'}}}}}"); assertResult(SAMPLE, "h.i", true, "{'h':{'i':{'j':{'k':{'l':'l_value'}}}}}");
assertResult(SAMPLE, "h.i.j", "{'h':{'i':{'j':{'k':{'l':'l_value'}}}}}"); assertResult(SAMPLE, "h.i.j", true, "{'h':{'i':{'j':{'k':{'l':'l_value'}}}}}");
assertResult(SAMPLE, "h.i.j.k", "{'h':{'i':{'j':{'k':{'l':'l_value'}}}}}"); assertResult(SAMPLE, "h.i.j.k", true, "{'h':{'i':{'j':{'k':{'l':'l_value'}}}}}");
assertResult(SAMPLE, "h.i.j.k.l", "{'h':{'i':{'j':{'k':{'l':'l_value'}}}}}"); assertResult(SAMPLE, "h.i.j.k.l", true, "{'h':{'i':{'j':{'k':{'l':'l_value'}}}}}");
assertResult(SAMPLE, "h.*", "{'h':{'i':{'j':{'k':{'l':'l_value'}}}}}"); assertResult(SAMPLE, "h.*", true, "{'h':{'i':{'j':{'k':{'l':'l_value'}}}}}");
assertResult(SAMPLE, "*.i", "{'h':{'i':{'j':{'k':{'l':'l_value'}}}}}"); assertResult(SAMPLE, "*.i", true, "{'h':{'i':{'j':{'k':{'l':'l_value'}}}}}");
assertResult(SAMPLE, "*.i.j", "{'h':{'i':{'j':{'k':{'l':'l_value'}}}}}"); assertResult(SAMPLE, "*.i.j", true, "{'h':{'i':{'j':{'k':{'l':'l_value'}}}}}");
assertResult(SAMPLE, "h.*.j", "{'h':{'i':{'j':{'k':{'l':'l_value'}}}}}"); assertResult(SAMPLE, "h.*.j", true, "{'h':{'i':{'j':{'k':{'l':'l_value'}}}}}");
assertResult(SAMPLE, "h.i.*", "{'h':{'i':{'j':{'k':{'l':'l_value'}}}}}"); assertResult(SAMPLE, "h.i.*", true, "{'h':{'i':{'j':{'k':{'l':'l_value'}}}}}");
assertResult(SAMPLE, "*.i.j.k", "{'h':{'i':{'j':{'k':{'l':'l_value'}}}}}"); assertResult(SAMPLE, "*.i.j.k", true, "{'h':{'i':{'j':{'k':{'l':'l_value'}}}}}");
assertResult(SAMPLE, "h.*.j.k", "{'h':{'i':{'j':{'k':{'l':'l_value'}}}}}"); assertResult(SAMPLE, "h.*.j.k", true, "{'h':{'i':{'j':{'k':{'l':'l_value'}}}}}");
assertResult(SAMPLE, "h.i.*.k", "{'h':{'i':{'j':{'k':{'l':'l_value'}}}}}"); assertResult(SAMPLE, "h.i.*.k", true, "{'h':{'i':{'j':{'k':{'l':'l_value'}}}}}");
assertResult(SAMPLE, "h.i.j.*", "{'h':{'i':{'j':{'k':{'l':'l_value'}}}}}"); assertResult(SAMPLE, "h.i.j.*", true, "{'h':{'i':{'j':{'k':{'l':'l_value'}}}}}");
assertResult(SAMPLE, "*.i.j.k.l", "{'h':{'i':{'j':{'k':{'l':'l_value'}}}}}"); assertResult(SAMPLE, "*.i.j.k.l", true, "{'h':{'i':{'j':{'k':{'l':'l_value'}}}}}");
assertResult(SAMPLE, "h.*.j.k.l", "{'h':{'i':{'j':{'k':{'l':'l_value'}}}}}"); assertResult(SAMPLE, "h.*.j.k.l", true, "{'h':{'i':{'j':{'k':{'l':'l_value'}}}}}");
assertResult(SAMPLE, "h.i.*.k.l", "{'h':{'i':{'j':{'k':{'l':'l_value'}}}}}"); assertResult(SAMPLE, "h.i.*.k.l", true, "{'h':{'i':{'j':{'k':{'l':'l_value'}}}}}");
assertResult(SAMPLE, "h.i.j.*.l", "{'h':{'i':{'j':{'k':{'l':'l_value'}}}}}"); assertResult(SAMPLE, "h.i.j.*.l", true, "{'h':{'i':{'j':{'k':{'l':'l_value'}}}}}");
assertResult(SAMPLE, "h.i.j.k.*", "{'h':{'i':{'j':{'k':{'l':'l_value'}}}}}"); assertResult(SAMPLE, "h.i.j.k.*", true, "{'h':{'i':{'j':{'k':{'l':'l_value'}}}}}");
assertResult(SAMPLE, "h.*.j.*.l", "{'h':{'i':{'j':{'k':{'l':'l_value'}}}}}"); assertResult(SAMPLE, "h.*.j.*.l", true, "{'h':{'i':{'j':{'k':{'l':'l_value'}}}}}");
assertResult(SAMPLE, "**.l", "{'h':{'i':{'j':{'k':{'l':'l_value'}}}}}"); assertResult(SAMPLE, "**.l", true, "{'h':{'i':{'j':{'k':{'l':'l_value'}}}}}");
assertResult(SAMPLE, "**.*2", "{'e':[{'f2':'f2_value'},{'g2':'g2_value'}]}"); assertResult(SAMPLE, "**.*2", true, "{'e':[{'f2':'f2_value'},{'g2':'g2_value'}]}");
} }
public void testFiltersWithDots() throws Exception { public void testExclusiveFilters() throws Exception {
assertResult("{'a':0,'b.c':'value','b':{'c':'c_value'}}", "b.c", "{'b':{'c':'c_value'}}"); final String SAMPLE = "{'a':0,'b':true,'c':'c_value','d':[0,1,2],'e':[{'f1':'f1_value','f2':'f2_value'},{'g1':'g1_value','g2':'g2_value'}],'h':{'i':{'j':{'k':{'l':'l_value'}}}}}";
assertResult("{'a':0,'b.c':'value','b':{'c':'c_value'}}", "b\\.c", "{'b.c':'value'}");
assertResult(SAMPLE, "a", false, "{'b':true,'c':'c_value','d':[0,1,2],'e':[{'f1':'f1_value','f2':'f2_value'},{'g1':'g1_value','g2':'g2_value'}],'h':{'i':{'j':{'k':{'l':'l_value'}}}}}");
assertResult(SAMPLE, "b", false, "{'a':0,'c':'c_value','d':[0,1,2],'e':[{'f1':'f1_value','f2':'f2_value'},{'g1':'g1_value','g2':'g2_value'}],'h':{'i':{'j':{'k':{'l':'l_value'}}}}}");
assertResult(SAMPLE, "c", false, "{'a':0,'b':true,'d':[0,1,2],'e':[{'f1':'f1_value','f2':'f2_value'},{'g1':'g1_value','g2':'g2_value'}],'h':{'i':{'j':{'k':{'l':'l_value'}}}}}");
assertResult(SAMPLE, "d", false, "{'a':0,'b':true,'c':'c_value','e':[{'f1':'f1_value','f2':'f2_value'},{'g1':'g1_value','g2':'g2_value'}],'h':{'i':{'j':{'k':{'l':'l_value'}}}}}");
assertResult(SAMPLE, "e", false, "{'a':0,'b':true,'c':'c_value','d':[0,1,2],'h':{'i':{'j':{'k':{'l':'l_value'}}}}}");
assertResult(SAMPLE, "h", false, "{'a':0,'b':true,'c':'c_value','d':[0,1,2],'e':[{'f1':'f1_value','f2':'f2_value'},{'g1':'g1_value','g2':'g2_value'}]}");
assertResult(SAMPLE, "z", false, "{'a':0,'b':true,'c':'c_value','d':[0,1,2],'e':[{'f1':'f1_value','f2':'f2_value'},{'g1':'g1_value','g2':'g2_value'}],'h':{'i':{'j':{'k':{'l':'l_value'}}}}}");
assertResult(SAMPLE, "e.f1", false, "{'a':0,'b':true,'c':'c_value','d':[0,1,2],'e':[{'f2':'f2_value'},{'g1':'g1_value','g2':'g2_value'}],'h':{'i':{'j':{'k':{'l':'l_value'}}}}}");
assertResult(SAMPLE, "e.f2", false, "{'a':0,'b':true,'c':'c_value','d':[0,1,2],'e':[{'f1':'f1_value'},{'g1':'g1_value','g2':'g2_value'}],'h':{'i':{'j':{'k':{'l':'l_value'}}}}}");
assertResult(SAMPLE, "e.f*", false, "{'a':0,'b':true,'c':'c_value','d':[0,1,2],'e':[{'g1':'g1_value','g2':'g2_value'}],'h':{'i':{'j':{'k':{'l':'l_value'}}}}}");
assertResult(SAMPLE, "e.*2", false, "{'a':0,'b':true,'c':'c_value','d':[0,1,2],'e':[{'f1':'f1_value'},{'g1':'g1_value'}],'h':{'i':{'j':{'k':{'l':'l_value'}}}}}");
assertResult(SAMPLE, "h.i", false, "{'a':0,'b':true,'c':'c_value','d':[0,1,2],'e':[{'f1':'f1_value','f2':'f2_value'},{'g1':'g1_value','g2':'g2_value'}]}");
assertResult(SAMPLE, "h.i.j", false, "{'a':0,'b':true,'c':'c_value','d':[0,1,2],'e':[{'f1':'f1_value','f2':'f2_value'},{'g1':'g1_value','g2':'g2_value'}]}");
assertResult(SAMPLE, "h.i.j.k", false, "{'a':0,'b':true,'c':'c_value','d':[0,1,2],'e':[{'f1':'f1_value','f2':'f2_value'},{'g1':'g1_value','g2':'g2_value'}]}");
assertResult(SAMPLE, "h.i.j.k.l", false, "{'a':0,'b':true,'c':'c_value','d':[0,1,2],'e':[{'f1':'f1_value','f2':'f2_value'},{'g1':'g1_value','g2':'g2_value'}]}");
assertResult(SAMPLE, "h.*", false, "{'a':0,'b':true,'c':'c_value','d':[0,1,2],'e':[{'f1':'f1_value','f2':'f2_value'},{'g1':'g1_value','g2':'g2_value'}]}");
assertResult(SAMPLE, "*.i", false, "{'a':0,'b':true,'c':'c_value','d':[0,1,2],'e':[{'f1':'f1_value','f2':'f2_value'},{'g1':'g1_value','g2':'g2_value'}]}");
assertResult(SAMPLE, "*.i.j", false, "{'a':0,'b':true,'c':'c_value','d':[0,1,2],'e':[{'f1':'f1_value','f2':'f2_value'},{'g1':'g1_value','g2':'g2_value'}]}");
assertResult(SAMPLE, "h.*.j", false, "{'a':0,'b':true,'c':'c_value','d':[0,1,2],'e':[{'f1':'f1_value','f2':'f2_value'},{'g1':'g1_value','g2':'g2_value'}]}");
assertResult(SAMPLE, "h.i.*", false, "{'a':0,'b':true,'c':'c_value','d':[0,1,2],'e':[{'f1':'f1_value','f2':'f2_value'},{'g1':'g1_value','g2':'g2_value'}]}");
assertResult(SAMPLE, "*.i.j.k", false, "{'a':0,'b':true,'c':'c_value','d':[0,1,2],'e':[{'f1':'f1_value','f2':'f2_value'},{'g1':'g1_value','g2':'g2_value'}]}");
assertResult(SAMPLE, "h.*.j.k", false, "{'a':0,'b':true,'c':'c_value','d':[0,1,2],'e':[{'f1':'f1_value','f2':'f2_value'},{'g1':'g1_value','g2':'g2_value'}]}");
assertResult(SAMPLE, "h.i.*.k", false, "{'a':0,'b':true,'c':'c_value','d':[0,1,2],'e':[{'f1':'f1_value','f2':'f2_value'},{'g1':'g1_value','g2':'g2_value'}]}");
assertResult(SAMPLE, "h.i.j.*", false, "{'a':0,'b':true,'c':'c_value','d':[0,1,2],'e':[{'f1':'f1_value','f2':'f2_value'},{'g1':'g1_value','g2':'g2_value'}]}");
assertResult(SAMPLE, "*.i.j.k.l", false, "{'a':0,'b':true,'c':'c_value','d':[0,1,2],'e':[{'f1':'f1_value','f2':'f2_value'},{'g1':'g1_value','g2':'g2_value'}]}");
assertResult(SAMPLE, "h.*.j.k.l", false, "{'a':0,'b':true,'c':'c_value','d':[0,1,2],'e':[{'f1':'f1_value','f2':'f2_value'},{'g1':'g1_value','g2':'g2_value'}]}");
assertResult(SAMPLE, "h.i.*.k.l", false, "{'a':0,'b':true,'c':'c_value','d':[0,1,2],'e':[{'f1':'f1_value','f2':'f2_value'},{'g1':'g1_value','g2':'g2_value'}]}");
assertResult(SAMPLE, "h.i.j.*.l", false, "{'a':0,'b':true,'c':'c_value','d':[0,1,2],'e':[{'f1':'f1_value','f2':'f2_value'},{'g1':'g1_value','g2':'g2_value'}]}");
assertResult(SAMPLE, "h.i.j.k.*", false, "{'a':0,'b':true,'c':'c_value','d':[0,1,2],'e':[{'f1':'f1_value','f2':'f2_value'},{'g1':'g1_value','g2':'g2_value'}]}");
assertResult(SAMPLE, "h.*.j.*.l", false, "{'a':0,'b':true,'c':'c_value','d':[0,1,2],'e':[{'f1':'f1_value','f2':'f2_value'},{'g1':'g1_value','g2':'g2_value'}]}");
assertResult(SAMPLE, "**.l", false, "{'a':0,'b':true,'c':'c_value','d':[0,1,2],'e':[{'f1':'f1_value','f2':'f2_value'},{'g1':'g1_value','g2':'g2_value'}]}");
assertResult(SAMPLE, "**.*2", false, "{'a':0,'b':true,'c':'c_value','d':[0,1,2],'e':[{'f1':'f1_value'},{'g1':'g1_value'}],'h':{'i':{'j':{'k':{'l':'l_value'}}}}}");
} }
private void assertResult(String input, String filter, String expected) throws Exception { public void testInclusiveFiltersWithDots() throws Exception {
assertResult("{'a':0,'b.c':'value','b':{'c':'c_value'}}", "b.c", true, "{'b':{'c':'c_value'}}");
assertResult("{'a':0,'b.c':'value','b':{'c':'c_value'}}", "b\\.c", true, "{'b.c':'value'}");
}
public void testExclusiveFiltersWithDots() throws Exception {
assertResult("{'a':0,'b.c':'value','b':{'c':'c_value'}}", "b.c", false, "{'a':0,'b.c':'value'}");
assertResult("{'a':0,'b.c':'value','b':{'c':'c_value'}}", "b\\.c", false, "{'a':0,'b':{'c':'c_value'}}");
}
private void assertResult(String input, String filter, boolean inclusive, String expected) throws Exception {
try (BytesStreamOutput os = new BytesStreamOutput()) { try (BytesStreamOutput os = new BytesStreamOutput()) {
try (FilteringGeneratorDelegate generator = new FilteringGeneratorDelegate(JSON_FACTORY.createGenerator(os), new FilterPathBasedFilter(new String[]{filter}), true, true)) { try (FilteringGeneratorDelegate generator = new FilteringGeneratorDelegate(JSON_FACTORY.createGenerator(os),
new FilterPathBasedFilter(new String[] { filter }, inclusive), true, true)) {
try (JsonParser parser = JSON_FACTORY.createParser(replaceQuotes(input))) { try (JsonParser parser = JSON_FACTORY.createParser(replaceQuotes(input))) {
while (parser.nextToken() != null) { while (parser.nextToken() != null) {
generator.copyCurrentStructure(parser); generator.copyCurrentStructure(parser);