XContentExtraction: Fix state bug
This fixes a nasty bug, when trying to extract arrays, that contain objects from a searchinput. Reason for this is, that we reset the state to early, while still being in an array and not having read all of the embedded objects. With Jackson 2.6 we should reuse jacksons capabilities to not only filter for xcontent builders, but also for parsers. Not the nicest code ever. Closes elastic/elasticsearch#852 Original commit: elastic/x-pack-elasticsearch@2682254644
This commit is contained in:
parent
6106128272
commit
bf4c42a40f
|
@ -33,6 +33,10 @@ public final class XContentFilterKeysUtils {
|
|||
}
|
||||
|
||||
private static Map<String, Object> parse(XContentParser parser, State state) throws IOException {
|
||||
return parse(parser, state, true);
|
||||
}
|
||||
|
||||
private static Map<String, Object> parse(XContentParser parser, State state, boolean isOutsideOfArray) throws IOException {
|
||||
if (state.includeLeaf) {
|
||||
return parser.map();
|
||||
}
|
||||
|
@ -46,12 +50,14 @@ public final class XContentFilterKeysUtils {
|
|||
case START_OBJECT:
|
||||
if (state.includeKey) {
|
||||
String fieldName = state.currentFieldName();
|
||||
Map<String, Object> nestedData = parse(parser, state);
|
||||
Map<String, Object> nestedData = parse(parser, state, isOutsideOfArray);
|
||||
data.put(fieldName, nestedData);
|
||||
} else {
|
||||
parser.skipChildren();
|
||||
}
|
||||
state.previousField();
|
||||
if (isOutsideOfArray) {
|
||||
state.previousField();
|
||||
}
|
||||
break;
|
||||
case START_ARRAY:
|
||||
if (state.includeKey) {
|
||||
|
@ -91,7 +97,7 @@ public final class XContentFilterKeysUtils {
|
|||
for (XContentParser.Token token = parser.nextToken(); token != END_ARRAY; token = parser.nextToken()) {
|
||||
switch (token) {
|
||||
case START_OBJECT:
|
||||
values.add(parse(parser, state));
|
||||
values.add(parse(parser, state, false));
|
||||
break;
|
||||
case VALUE_STRING:
|
||||
values.add(parser.text());
|
||||
|
|
|
@ -12,15 +12,12 @@ import org.elasticsearch.common.xcontent.XContentHelper;
|
|||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
/**
|
||||
*/
|
||||
|
@ -114,6 +111,29 @@ public class FilterXContentTests extends ESTestCase {
|
|||
assertThat(selectMap(filteredData, "leaf3", "key2").get("key2"), Matchers.<Object>equalTo("value2"));
|
||||
}
|
||||
|
||||
// issue #852
|
||||
public void testArraysAreNotCutOff() throws Exception {
|
||||
XContentBuilder builder = jsonBuilder().startObject().startArray("buckets")
|
||||
.startObject().startObject("foo").startObject("values").endObject().endObject().endObject()
|
||||
.startObject().startObject("foo").startObject("values").endObject().endObject().endObject()
|
||||
.endArray().endObject();
|
||||
|
||||
XContentParser parser = XContentHelper.createParser(builder.bytes());
|
||||
|
||||
Set<String> keys = new HashSet<>();
|
||||
keys.add("buckets.foo.values");
|
||||
|
||||
Map<String, Object> filteredData = XContentFilterKeysUtils.filterMapOrdered(keys, parser);
|
||||
assertThat(filteredData.get("buckets"), instanceOf(List.class));
|
||||
|
||||
// both buckets have to include the following keys
|
||||
List<Map<String, Object>> buckets = (List<Map<String, Object>>) filteredData.get("buckets");
|
||||
assertThat(buckets, hasSize(2));
|
||||
assertThat(buckets.get(0).keySet(), containsInAnyOrder("foo"));
|
||||
assertThat(buckets.get(1).keySet(), containsInAnyOrder("foo"));
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static Map<String, Object> selectMap(Map<String, Object> data, String... path) {
|
||||
for (String element : path) {
|
||||
|
|
Loading…
Reference in New Issue