Reg: Proposal: Generalized Number.parseNumber(String) Method for Java

Sathish Kumar Thiyagarajan sathishkumar.thiyagarajan at gmail.com
Tue Apr 1 05:58:12 UTC 2025


Sure, Volkan.

Let me explain with a sample use case (I also have the source code
available on GitHub at https://github.com/sathishk/parse-number ).

> When developing *REST APIs or Data Engineering applications*, we often
> deal with *untyped JSON documents*, which are loaded into Java as Map<String,
> Object> (for JSON objects) or List<Object> (for JSON arrays). Typically,
> JSON parsers convert these into Java objects.

Consider this example:

Map<String, Number> originalData = Map.of(
    "byteValue", (byte) 123,
    "shortValue", (short) 1234
);

This would be represented as the following JSON:

{
  "shortValue": 1234,
  "byteValue": 123
}

Now, when we *deserialize* this JSON using a parser like Jackson
<https://www.baeldung.com/java-json-maps-comparison#1-using-jackson>:

Map<String, Object> deserializedData = new
JsonReader().getJacksonMap(jsonString);

The expectation is that *numeric values should be preserved in their
smallest possible type* (byte or short). However, *Jackson (and most JSON
parsers) default to Integer for whole numbers* because they rely on
Integer.parseInt(String), which is a safe fallback for most cases.
Why Number.parseNumber(String)?

If we had a *generalized Number.parseNumber(String) method*, it could
intelligently determine the most memory-efficient number type based on the
value range. This would help reduce unnecessary memory usage, especially
when handling large datasets in *high-performance applications*.

Would love to hear your thoughts on this approach!

Thanks & Regards,
Sathish Kumar Thiyagarajan

On Mon, 31 Mar 2025 at 14:56, Volkan Yazıcı <volkan at yazi.ci> wrote:

> Sathish, would you mind elaborating on your use case a bit more, please?
> That is, I am not able to see where and how you want to leverage
> `Number#parseNumber(String)` in the `testNumberMemoryUsage()` method.
> Example: *"I have this test method verifying this behavior of that
> application. Given a `Number#parseNumber(String)`, I can improve this as
> follows."*
>
> On Fri, Mar 28, 2025 at 6:31 PM Sathish Kumar Thiyagarajan <
> sathishkumar.thiyagarajan at gmail.com> wrote:
>
>> Dear Core-Libs Dev Team,
>>
>> *Note:* I have now subscribed to the mailing list and am resending this
>> message as advised.
>>
>> I would like to propose an improvement to the JDK: a *generalized
>> Number.parseNumber(String) method*.
>> Motivation
>>
>> Java provides multiple number types (byte, short, int, long, etc.), and
>> developers typically choose them based on memory considerations. Currently,
>> Java offers String to Number conversions using concrete classes:
>>
>>    -
>>
>>    Long.parseLong(String)
>>    -
>>
>>    Integer.parseInt(String)
>>    -
>>
>>    Short.parseShort(String), etc.
>>
>> While these are useful, Java lacks a *generalized method* that returns
>> the most memory-efficient Number representation based on the input, like:
>>
>> Number.parseNumber(String numberAsText);
>>
>> Use Case: JSON Serialization
>>
>> This would be particularly useful in cases like *JSON serialization in
>> REST APIs (Using Jackson <https://github.com/FasterXML/jackson>)*, where
>> number types are often altered during serialization/deserialization.
>> Consider the following test case:
>>
>> @Test
>> void testNumberMemoryUsage() throws JsonProcessingException {
>>     ObjectMapper mapper = new ObjectMapper();
>>     Map<String, Object> numbersObject = Map.of("aShort", (short) 1234, "aFloat", (float) 1.33);
>>
>>     final String jsonText = mapper.writeValueAsString(numbersObject);
>>     Map<String, Object> parsedJsonObject = mapper.readValue(jsonText, new TypeReference<>() {});
>>
>>     // Expected: Short.class | Actual: Integer.class
>>     assertEquals(Short.class, parsedJsonObject.get("aShort").getClass());
>>
>>     // Expected: Float.class | Actual: Double.class
>>     assertEquals(Float.class, parsedJsonObject.get("aFloat").getClass());
>> }
>>
>> Reference Implementation
>>
>> Here’s a rough implementation to illustrate the idea:
>>
>> private static Number parseNumber(final String numberStr) {
>>     try {
>>         if (numberStr.contains(".")) {
>>             double doubleValue = Double.parseDouble(numberStr);
>>             return (doubleValue >= -Float.MAX_VALUE && doubleValue <= Float.MAX_VALUE) ?
>>                    (float) doubleValue : doubleValue;
>>         } else {
>>             long longValue = Long.parseLong(numberStr);
>>             if (longValue >= Byte.MIN_VALUE && longValue <= Byte.MAX_VALUE) {
>>                 return (byte) longValue;
>>             } else if (longValue >= Short.MIN_VALUE && longValue <= Short.MAX_VALUE) {
>>                 return (short) longValue;
>>             } else if (longValue >= Integer.MIN_VALUE && longValue <= Integer.MAX_VALUE) {
>>                 return (int) longValue;
>>             } else {
>>                 return longValue;
>>             }
>>         }
>>     } catch (NumberFormatException e) {
>>         return parseBigNumber(numberStr);
>>     }
>> }
>>
>> private static Number parseBigNumber(final String numberStr) {
>>     try {
>>         return new BigInteger(numberStr); // Try BigInteger first
>>     } catch (NumberFormatException e) {
>>         // Only create BigDecimal if BigInteger fails
>>         BigDecimal bd = new BigDecimal(numberStr);
>>         try {
>>             // Convert to BigInteger if there's no fraction
>>             return bd.toBigIntegerExact();
>>         } catch (ArithmeticException ex) {
>>             return bd; // If it's a decimal, return BigDecimal
>>         }
>>     }
>> }
>>
>> Would love to hear your thoughts on this proposal. Appreciate your
>> feedback and guidance!
>>
>> Thanks & Regards,
>> Sathish Kumar Thiyagarajan
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/core-libs-dev/attachments/20250401/ada71485/attachment-0001.htm>


More information about the core-libs-dev mailing list