-
Notifications
You must be signed in to change notification settings - Fork 25.8k
Making JsonProcessor stricter so that it does not silently drop data #93179
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
62f40cf
8218026
9bf46a6
67caf61
d5f7a6c
fa5a514
37b805e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| pr: 93179 | ||
| summary: Making `JsonProcessor` stricter so that it does not silently drop data | ||
| area: Ingest Node | ||
| type: bug | ||
| issues: | ||
| - 92898 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,11 +20,14 @@ | |
| import java.util.HashMap; | ||
| import java.util.List; | ||
| import java.util.Map; | ||
| import java.util.stream.Collectors; | ||
|
|
||
| import static org.elasticsearch.ingest.common.JsonProcessor.ConflictStrategy.MERGE; | ||
| import static org.elasticsearch.ingest.common.JsonProcessor.ConflictStrategy.REPLACE; | ||
| import static org.hamcrest.Matchers.closeTo; | ||
| import static org.hamcrest.Matchers.containsString; | ||
| import static org.hamcrest.Matchers.equalTo; | ||
| import static org.hamcrest.Matchers.instanceOf; | ||
|
|
||
| public class JsonProcessorTests extends ESTestCase { | ||
|
|
||
|
|
@@ -234,4 +237,86 @@ public void testAddBoolToRoot() { | |
| Exception exception = expectThrows(IllegalArgumentException.class, () -> jsonProcessor.execute(ingestDocument)); | ||
| assertThat(exception.getMessage(), containsString("cannot add non-map fields to root of document")); | ||
| } | ||
|
|
||
| @SuppressWarnings({ "unchecked", "rawtypes" }) | ||
| public void testApply() { | ||
| { | ||
| Object result = JsonProcessor.apply("{\"foo\":\"bar\"}", true, true); | ||
| assertThat(result, instanceOf(Map.class)); | ||
| Map resultMap = (Map) result; | ||
| assertThat(resultMap.size(), equalTo(1)); | ||
| assertThat(resultMap.get("foo"), equalTo("bar")); | ||
| } | ||
| { | ||
| Object result = JsonProcessor.apply("\"foo\"", true, true); | ||
| assertThat(result, instanceOf(String.class)); | ||
| assertThat(result, equalTo("foo")); | ||
| } | ||
| { | ||
| boolean boolValue = randomBoolean(); | ||
| Object result = JsonProcessor.apply(Boolean.toString(boolValue), true, true); | ||
| assertThat(result, instanceOf(Boolean.class)); | ||
| assertThat(result, equalTo(boolValue)); | ||
| } | ||
| { | ||
| double value = randomDouble(); | ||
| Object result = JsonProcessor.apply(Double.toString(value), true, true); | ||
| assertThat(result, instanceOf(Double.class)); | ||
| assertThat((double) result, closeTo(value, .001)); | ||
| } | ||
| { | ||
| List<Double> list = randomList(10, ESTestCase::randomDouble); | ||
| String value = list.stream().map(val -> Double.toString(val)).collect(Collectors.joining(",", "[", "]")); | ||
| Object result = JsonProcessor.apply(value, true, true); | ||
| assertThat(result, instanceOf(List.class)); | ||
| List<Double> resultList = (List<Double>) result; | ||
| assertThat(resultList.size(), equalTo(list.size())); | ||
| for (int i = 0; i < list.size(); i++) { | ||
| assertThat(resultList.get(i), closeTo(list.get(i), .001)); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| @SuppressWarnings({ "unchecked", "rawtypes" }) | ||
| public void testApplyWithInvalidJson() { | ||
| /* | ||
| * The following fail whether strictJsonParsing is set to true or false. The reason is that even the first token cannot be parsed | ||
| * as JSON (since the first token is a not a primitive or an object -- just characters not in quotes). | ||
| */ | ||
| expectThrows(IllegalArgumentException.class, () -> JsonProcessor.apply("foo", true, true)); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why are these expected to fail? A comment would help. |
||
| expectThrows(IllegalArgumentException.class, () -> JsonProcessor.apply("foo", true, false)); | ||
| expectThrows(IllegalArgumentException.class, () -> JsonProcessor.apply("foo [360113.865822] wbrdg-0afe001ce", true, true)); | ||
| expectThrows(IllegalArgumentException.class, () -> JsonProcessor.apply("foo [360113.865822] wbrdg-0afe001ce", true, false)); | ||
|
|
||
| /* | ||
| * The following are examples of malformed json but the first part of each is valid json. Previously apply parsed just the first | ||
| * token and ignored the rest, but it now throw an IllegalArgumentException unless strictJsonParsing is set to false. See | ||
| * https://github.com/elastic/elasticsearch/issues/92898. | ||
| */ | ||
| expectThrows(IllegalArgumentException.class, () -> JsonProcessor.apply("123 foo", true, true)); | ||
| expectThrows(IllegalArgumentException.class, () -> JsonProcessor.apply("45 this is {\"a\": \"json\"}", true, true)); | ||
|
|
||
| { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These are all good. Maybe split into a separate test just to make it clear that we're testing for something different than the code above? Basically, maybe the "strict validation" stuff could be its own test. |
||
| expectThrows(IllegalArgumentException.class, () -> JsonProcessor.apply("[360113.865822] wbrdg-0afe001ce", true, true)); | ||
| Object result = JsonProcessor.apply("[360113.865822] wbrdg-0afe001ce", true, false); | ||
| assertThat(result, instanceOf(List.class)); | ||
| List<Double> resultList = (List<Double>) result; | ||
| assertThat(resultList.size(), equalTo(1)); | ||
| assertThat(resultList.get(0), closeTo(360113.865822, .001)); | ||
| } | ||
| { | ||
| expectThrows(IllegalArgumentException.class, () -> JsonProcessor.apply("{\"foo\":\"bar\"} wbrdg-0afe00e", true, true)); | ||
| Object result = JsonProcessor.apply("{\"foo\":\"bar\"} wbrdg-0afe00e", true, false); | ||
| assertThat(result, instanceOf(Map.class)); | ||
| Map resultMap = (Map) result; | ||
| assertThat(resultMap.size(), equalTo(1)); | ||
| assertThat(resultMap.get("foo"), equalTo("bar")); | ||
| } | ||
| { | ||
| expectThrows(IllegalArgumentException.class, () -> JsonProcessor.apply(" 1268 : TimeOut = 123 : a", true, true)); | ||
| Object result = JsonProcessor.apply(" 1268 : TimeOut = 123 : a", true, false); | ||
| assertThat(result, instanceOf(Integer.class)); | ||
| assertThat(result, equalTo(1268)); | ||
| } | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With the default being strict, does this count as a breaking change now or are we classifying this as a bug?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought we had agreed it was a bug.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couldn't remember. If so, all good!