diff --git a/docs/changelog/129005.yaml b/docs/changelog/129005.yaml new file mode 100644 index 000000000000..5d6339096a8b --- /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 351bfdc4b7d4..8371fcfdcda6 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 @@ -87,7 +87,13 @@ public abstract class AbstractXContentParser implements XContentParser { 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; }; } @@ -96,7 +102,11 @@ public abstract class AbstractXContentParser implements XContentParser { 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 1c968c2ab4a7..ca72a504c304 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 class MapXContentParserTests extends ESTestCase { } } + 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);