This is an automated email from the ASF dual-hosted git repository.

snuyanzin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/flink.git


The following commit(s) were added to refs/heads/master by this push:
     new fed133939df [FLINK-40218][core] Store a `JSON` number literal in the 
`VARIANT` builder like `PARSE_JSON`
fed133939df is described below

commit fed133939df542016dbbb0e892a11eacbf9b93ae
Author: Ramin Gharib <[email protected]>
AuthorDate: Sat Oct 10 14:38:07 2026 +0200

    [FLINK-40218][core] Store a `JSON` number literal in the `VARIANT` builder 
like `PARSE_JSON`
---
 .../variant/BinaryVariantInternalBuilder.java      | 23 ++++++
 .../variant/BinaryVariantInternalBuilderTest.java  | 81 ++++++++++++++++++++++
 2 files changed, 104 insertions(+)

diff --git 
a/flink-core/src/main/java/org/apache/flink/types/variant/BinaryVariantInternalBuilder.java
 
b/flink-core/src/main/java/org/apache/flink/types/variant/BinaryVariantInternalBuilder.java
index 0143f81da41..7e1d952343e 100644
--- 
a/flink-core/src/main/java/org/apache/flink/types/variant/BinaryVariantInternalBuilder.java
+++ 
b/flink-core/src/main/java/org/apache/flink/types/variant/BinaryVariantInternalBuilder.java
@@ -345,6 +345,29 @@ public class BinaryVariantInternalBuilder {
         }
     }
 
+    /**
+     * Appends a JSON number literal the way {@link #parseJson(String, 
boolean)} stores it: as the
+     * smallest integer that holds it, else as a decimal, else as a double. A 
caller that holds JSON
+     * in another form, such as a tree built by its own Jackson, uses this so 
its numbers match
+     * {@code PARSE_JSON}. The literal is read with the same parser and number 
handling as {@code
+     * PARSE_JSON}, so surrounding whitespace is allowed.
+     *
+     * @throws IOException if {@code literal} is not exactly one JSON number, 
or is out of the range
+     *     of a double. The builder must not be used after that.
+     */
+    void appendJsonNumber(String literal) throws IOException {
+        try (JsonParser parser = JSON_FACTORY.createParser(literal)) {
+            final JsonToken token = parser.nextToken();
+            if (token != JsonToken.VALUE_NUMBER_INT && token != 
JsonToken.VALUE_NUMBER_FLOAT) {
+                throw new JsonParseException(parser, "Expected a JSON number 
but got " + token);
+            }
+            buildJson(parser);
+            if (parser.nextToken() != null) {
+                throw new JsonParseException(parser, "Unexpected content after 
the JSON number");
+            }
+        }
+    }
+
     // The variant spec requires a scale in [0, 38] and a precision of at most 
38.
     private static BigDecimal toVariantDecimal(BigDecimal d) {
         BigDecimal result = d;
diff --git 
a/flink-core/src/test/java/org/apache/flink/types/variant/BinaryVariantInternalBuilderTest.java
 
b/flink-core/src/test/java/org/apache/flink/types/variant/BinaryVariantInternalBuilderTest.java
index 5a8e2c07254..2043381dc76 100644
--- 
a/flink-core/src/test/java/org/apache/flink/types/variant/BinaryVariantInternalBuilderTest.java
+++ 
b/flink-core/src/test/java/org/apache/flink/types/variant/BinaryVariantInternalBuilderTest.java
@@ -310,4 +310,85 @@ class BinaryVariantInternalBuilderTest {
                 // A negative scale is rescaled to 0.
                 Arguments.of(5L, -1, DECIMAL4));
     }
+
+    @ParameterizedTest
+    @ValueSource(
+            strings = {
+                "0",
+                "-0",
+                "127",
+                "128",
+                "-129",
+                "32768",
+                "2147483648",
+                "9223372036854775807",
+                "-9223372036854775808",
+                // Beyond a long: a decimal while it fits 38 digits, then a 
double.
+                "9223372036854775808",
+                "-9223372036854775809",
+                "123456789012345678901234567890123456789",
+                "3.14",
+                "-1.5",
+                "0.10",
+                "0.000000000000000000000000000000000000001",
+                "1e10",
+                "1E10",
+                "1e+10",
+                "1e-10",
+                "-1.5e3",
+                "1e308",
+                // Whitespace around a value is valid JSON.
+                " 1.5\n"
+            })
+    void testAppendJsonNumberMatchesParseJson(final String literal) throws 
IOException {
+        final BinaryVariantInternalBuilder builder = new 
BinaryVariantInternalBuilder(false);
+        builder.appendJsonNumber(literal);
+
+        assertThat(builder.build())
+                .isEqualTo(BinaryVariantInternalBuilder.parseJson(literal, 
false));
+    }
+
+    @ParameterizedTest
+    @ValueSource(
+            strings = {
+                // Locale-specific separators.
+                "1,5",
+                "1.000,5",
+                "1'000",
+                // Accepted by Java's number parsers, but not by JSON.
+                "+5",
+                "0x1p4",
+                "0x1.8p3",
+                "10d",
+                "1.5f",
+                "1" + (char) 0x06F8,
+                "NaN",
+                "Infinity",
+                "-Infinity",
+                // Incomplete or malformed.
+                "",
+                "-",
+                "01",
+                "-01",
+                "1.",
+                ".5",
+                "1e",
+                "1e+",
+                "1.5.5",
+                "--1",
+                // Another JSON value, or more than one.
+                "\"5\"",
+                "true",
+                "null",
+                "[1]",
+                "5 6",
+                // A JSON number outside the range of a double.
+                "1e400",
+                "-1e400"
+            })
+    void testAppendJsonNumberRejectsInvalidLiterals(final String literal) {
+        final BinaryVariantInternalBuilder builder = new 
BinaryVariantInternalBuilder(false);
+
+        assertThatThrownBy(() -> 
builder.appendJsonNumber(literal)).isInstanceOf(IOException.class);
+    }
 }

Reply via email to