diff --git a/docs/changelog/129005.yaml b/docs/changelog/129005.yaml new file mode 100644 index 0000000000000..5d6339096a8bb --- /dev/null +++ b/docs/changelog/129005.yaml @@ -0,0 +1,6 @@ +pr: 129005 +summary: Update AbstractXContentParser to support parsers that don't provide text + characters +area: Infra/Core +type: bug +issues: [] diff --git a/libs/x-content/src/main/java/org/elasticsearch/xcontent/support/AbstractXContentParser.java b/libs/x-content/src/main/java/org/elasticsearch/xcontent/support/AbstractXContentParser.java index 909cf808d1f34..03e6dd66ae2b9 100644 --- a/libs/x-content/src/main/java/org/elasticsearch/xcontent/support/AbstractXContentParser.java +++ b/libs/x-content/src/main/java/org/elasticsearch/xcontent/support/AbstractXContentParser.java @@ -85,7 +85,13 @@ void ensureNumberConversion(boolean coerce, long result, Class public boolean isBooleanValue() throws IOException { return switch (currentToken()) { case VALUE_BOOLEAN -> true; - case VALUE_STRING -> Booleans.isBoolean(textCharacters(), textOffset(), textLength()); + case VALUE_STRING -> { + if (hasTextCharacters()) { + yield Booleans.isBoolean(textCharacters(), textOffset(), textLength()); + } else { + yield Booleans.isBoolean(text()); + } + } default -> false; }; } @@ -94,7 +100,11 @@ public boolean isBooleanValue() throws IOException { public boolean booleanValue() throws IOException { Token token = currentToken(); if (token == Token.VALUE_STRING) { - return Booleans.parseBoolean(textCharacters(), textOffset(), textLength(), false /* irrelevant */); + if (hasTextCharacters()) { + return Booleans.parseBoolean(textCharacters(), textOffset(), textLength(), false /* irrelevant */); + } else { + return Booleans.parseBoolean(text(), false /* irrelevant */); + } } return doBooleanValue(); } diff --git a/libs/x-content/src/test/java/org/elasticsearch/xcontent/MapXContentParserTests.java b/libs/x-content/src/test/java/org/elasticsearch/xcontent/MapXContentParserTests.java index 1c968c2ab4a7c..ca72a504c3046 100644 --- a/libs/x-content/src/test/java/org/elasticsearch/xcontent/MapXContentParserTests.java +++ b/libs/x-content/src/test/java/org/elasticsearch/xcontent/MapXContentParserTests.java @@ -97,6 +97,40 @@ public void testCopyCurrentStructure() throws IOException { } } + public void testParseBooleanStringValue() throws IOException { + try ( + XContentParser parser = new MapXContentParser( + xContentRegistry(), + LoggingDeprecationHandler.INSTANCE, + Map.of("bool_key", "true"), + randomFrom(XContentType.values()) + ) + ) { + assertEquals(XContentParser.Token.START_OBJECT, parser.nextToken()); + assertEquals(XContentParser.Token.FIELD_NAME, parser.nextToken()); + assertEquals(XContentParser.Token.VALUE_STRING, parser.nextToken()); + assertTrue(parser.isBooleanValue()); + assertTrue(parser.booleanValue()); + assertEquals(XContentParser.Token.END_OBJECT, parser.nextToken()); + } + + try ( + XContentParser parser = new MapXContentParser( + xContentRegistry(), + LoggingDeprecationHandler.INSTANCE, + Map.of("bool_key", "false"), + randomFrom(XContentType.values()) + ) + ) { + assertEquals(XContentParser.Token.START_OBJECT, parser.nextToken()); + assertEquals(XContentParser.Token.FIELD_NAME, parser.nextToken()); + assertEquals(XContentParser.Token.VALUE_STRING, parser.nextToken()); + assertTrue(parser.isBooleanValue()); + assertFalse(parser.booleanValue()); + assertEquals(XContentParser.Token.END_OBJECT, parser.nextToken()); + } + } + private void compareTokens(CheckedConsumer consumer) throws IOException { for (XContentType xContentType : EnumSet.allOf(XContentType.class)) { logger.info("--> testing with xcontent type: {}", xContentType);