Watcher: Fix XContentFilterKeysUtils when using nested lists (elastic/elasticsearch#4635)

The ability to filter JSON inside of arrays was stopping after the first element was found.

Closes elastic/elasticsearch#4614

Original commit: elastic/x-pack-elasticsearch@452cf1c49d
This commit is contained in:
Alexander Reelsen 2017-01-20 12:22:20 +01:00 committed by GitHub
parent 8011912ce7
commit 84936d57ad
2 changed files with 68 additions and 3 deletions

View File

@ -79,19 +79,25 @@ public final class XContentFilterKeysUtils {
if (state.includeKey) { if (state.includeKey) {
data.put(state.currentFieldName(), parser.text()); data.put(state.currentFieldName(), parser.text());
} }
state.previousField(); if (isOutsideOfArray) {
state.previousField();
}
break; break;
case VALUE_NUMBER: case VALUE_NUMBER:
if (state.includeKey) { if (state.includeKey) {
data.put(state.currentFieldName(), parser.numberValue()); data.put(state.currentFieldName(), parser.numberValue());
} }
state.previousField(); if (isOutsideOfArray) {
state.previousField();
}
break; break;
case VALUE_BOOLEAN: case VALUE_BOOLEAN:
if (state.includeKey) { if (state.includeKey) {
data.put(state.currentFieldName(), parser.booleanValue()); data.put(state.currentFieldName(), parser.booleanValue());
} }
state.previousField(); if (isOutsideOfArray) {
state.previousField();
}
break; break;
} }
} }

View File

@ -9,8 +9,10 @@ import org.elasticsearch.common.collect.MapBuilder;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.xpack.watcher.support.xcontent.ObjectPath;
import org.hamcrest.Matchers; import org.hamcrest.Matchers;
import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
@ -23,6 +25,7 @@ import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
public class FilterXContentTests extends ESTestCase { public class FilterXContentTests extends ESTestCase {
public void testPayloadFiltering() throws Exception { public void testPayloadFiltering() throws Exception {
@ -136,6 +139,62 @@ public class FilterXContentTests extends ESTestCase {
assertThat(buckets.get(1).keySet(), containsInAnyOrder("foo")); assertThat(buckets.get(1).keySet(), containsInAnyOrder("foo"));
} }
// issue #4614
public void testNestedArraysWork() throws Exception {
XContentBuilder builder = jsonBuilder().startObject().startArray("buckets")
.startObject().startObject("foo").field("spam", "eggs").endObject().endObject()
.startObject().startObject("foo").field("spam", "eggs2").endObject().endObject()
.startObject().startObject("foo").field("spam", "eggs3").endObject().endObject()
.endArray().endObject();
XContentParser parser = createParser(builder);
assertArrayValues(parser, "buckets.foo.spam", "eggs", "eggs2", "eggs3");
}
private void assertArrayValues(XContentParser parser, String key, Object ... expectedValues) throws IOException {
Set<String> keys = new HashSet<>();
keys.add(key);
Map<String, Object> filteredData = XContentFilterKeysUtils.filterMapOrdered(keys, parser);
for (int i = 0; i < expectedValues.length; i++) {
if (expectedValues[i] instanceof String) {
String data = ObjectPath.eval("buckets." + i + ".foo.spam", filteredData);
assertThat(data, is(expectedValues[i]));
} else if (expectedValues[i] instanceof Integer) {
int data = ObjectPath.eval("buckets." + i + ".foo.spam", filteredData);
assertThat(data, is(expectedValues[i]));
} else if (expectedValues[i] instanceof Boolean) {
boolean data = ObjectPath.eval("buckets." + i + ".foo.spam", filteredData);
assertThat(data, is(expectedValues[i]));
}
}
}
public void testNestedArraysWorkWithNumbers() throws Exception {
XContentBuilder builder = jsonBuilder().startObject().startArray("buckets")
.startObject().startObject("foo").field("spam", 0).endObject().endObject()
.startObject().startObject("foo").field("spam", 1).endObject().endObject()
.startObject().startObject("foo").field("spam", 2).endObject().endObject()
.endArray().endObject();
XContentParser parser = createParser(builder);
assertArrayValues(parser, "buckets.foo.spam", 0, 1, 2);
}
public void testNestedArraysWorkWithBooleans() throws Exception {
boolean[] bools = new boolean[] { randomBoolean(), randomBoolean(), randomBoolean() };
XContentBuilder builder = jsonBuilder().startObject().startArray("buckets")
.startObject().startObject("foo").field("spam", bools[0]).endObject().endObject()
.startObject().startObject("foo").field("spam", bools[1]).endObject().endObject()
.startObject().startObject("foo").field("spam", bools[2]).endObject().endObject()
.endArray().endObject();
XContentParser parser = createParser(builder);
assertArrayValues(parser, "buckets.foo.spam", bools);
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private static Map<String, Object> selectMap(Map<String, Object> data, String... path) { private static Map<String, Object> selectMap(Map<String, Object> data, String... path) {