Reg: Proposal: Generalized Number.parseNumber(String) Method for Java
Sathish Kumar Thiyagarajan
sathishkumar.thiyagarajan at gmail.com
Fri Mar 28 17:29:01 UTC 2025
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/20250328/fa805eee/attachment-0001.htm>
More information about the core-libs-dev
mailing list