From b08fc788db5fa28ed51ec519373f063f142b110e Mon Sep 17 00:00:00 2001 From: Kannan J Date: Mon, 25 May 2026 13:59:21 +0000 Subject: [PATCH] core: support Integer and Long in service configuration parsing Previously, ManagedChannelImplBuilder and JsonUtil only supported Double or String for numeric values in service configurations. This caused IllegalArgumentException when using service configurations produced by JSON parsers like Jackson that represent non-decimal numbers as Integer or Long. This change: - Updates ManagedChannelImplBuilder to accept any Number type. - Enhances JsonUtil to robustly handle numeric conversions while maintaining necessary integral checks. - Adds ServiceConfigNumericTypeTest to verify support for Integer, Double, and Long types. Fixes #12815 --- .../main/java/io/grpc/internal/JsonUtil.java | 26 +++++++------- .../internal/ManagedChannelImplBuilder.java | 4 +-- .../ManagedChannelImplBuilderTest.java | 34 ++++++++++++++++++- 3 files changed, 49 insertions(+), 15 deletions(-) diff --git a/core/src/main/java/io/grpc/internal/JsonUtil.java b/core/src/main/java/io/grpc/internal/JsonUtil.java index 6c9274702b6..cce3725beca 100644 --- a/core/src/main/java/io/grpc/internal/JsonUtil.java +++ b/core/src/main/java/io/grpc/internal/JsonUtil.java @@ -106,8 +106,8 @@ public static Double getNumberAsDouble(Map obj, String key) { return null; } Object value = obj.get(key); - if (value instanceof Double) { - return (Double) value; + if (value instanceof Number) { + return ((Number) value).doubleValue(); } if (value instanceof String) { try { @@ -132,8 +132,8 @@ public static Float getNumberAsFloat(Map obj, String key) { return null; } Object value = obj.get(key); - if (value instanceof Float) { - return (Float) value; + if (value instanceof Number) { + return ((Number) value).floatValue(); } if (value instanceof String) { try { @@ -159,11 +159,12 @@ public static Integer getNumberAsInteger(Map obj, String key) { return null; } Object value = obj.get(key); - if (value instanceof Double) { - Double d = (Double) value; - int i = d.intValue(); + if (value instanceof Number) { + Number n = (Number) value; + double d = n.doubleValue(); + int i = n.intValue(); if (i != d) { - throw new ClassCastException("Number expected to be integer: " + d); + throw new ClassCastException("Number expected to be integer: " + n); } return i; } @@ -190,11 +191,12 @@ public static Long getNumberAsLong(Map obj, String key) { return null; } Object value = obj.get(key); - if (value instanceof Double) { - Double d = (Double) value; - long l = d.longValue(); + if (value instanceof Number) { + Number n = (Number) value; + double d = n.doubleValue(); + long l = n.longValue(); if (l != d) { - throw new ClassCastException("Number expected to be long: " + d); + throw new ClassCastException("Number expected to be long: " + n); } return l; } diff --git a/core/src/main/java/io/grpc/internal/ManagedChannelImplBuilder.java b/core/src/main/java/io/grpc/internal/ManagedChannelImplBuilder.java index 128c929ec0e..5224298984d 100644 --- a/core/src/main/java/io/grpc/internal/ManagedChannelImplBuilder.java +++ b/core/src/main/java/io/grpc/internal/ManagedChannelImplBuilder.java @@ -582,7 +582,7 @@ public ManagedChannelImplBuilder defaultServiceConfig(@Nullable Map s parsedMap.put(key, checkListEntryTypes((List) value)); } else if (value instanceof String) { parsedMap.put(key, value); - } else if (value instanceof Double) { + } else if (value instanceof Number) { parsedMap.put(key, value); } else if (value instanceof Boolean) { parsedMap.put(key, value); @@ -606,7 +606,7 @@ private static List checkListEntryTypes(List list) { parsedList.add(checkListEntryTypes((List) value)); } else if (value instanceof String) { parsedList.add(value); - } else if (value instanceof Double) { + } else if (value instanceof Number) { parsedList.add(value); } else if (value instanceof Boolean) { parsedList.add(value); diff --git a/core/src/test/java/io/grpc/internal/ManagedChannelImplBuilderTest.java b/core/src/test/java/io/grpc/internal/ManagedChannelImplBuilderTest.java index b0939239477..a34b4debb19 100644 --- a/core/src/test/java/io/grpc/internal/ManagedChannelImplBuilderTest.java +++ b/core/src/test/java/io/grpc/internal/ManagedChannelImplBuilderTest.java @@ -737,7 +737,39 @@ public void defaultServiceConfig_intValue() { Map config = new HashMap<>(); config.put("key", 3); - assertThrows(IllegalArgumentException.class, () -> builder.defaultServiceConfig(config)); + builder.defaultServiceConfig(config); + + assertThat(builder.defaultServiceConfig).containsExactlyEntriesIn(config); + } + + @Test + public void defaultServiceConfig_longValue() { + Map config = new HashMap<>(); + config.put("key", 3L); + + builder.defaultServiceConfig(config); + + assertThat(builder.defaultServiceConfig).containsExactlyEntriesIn(config); + } + + @Test + public void defaultServiceConfig_list_intValue() { + Map config = new HashMap<>(); + config.put("key", Collections.singletonList(3)); + + builder.defaultServiceConfig(config); + + assertThat(builder.defaultServiceConfig).containsExactlyEntriesIn(config); + } + + @Test + public void defaultServiceConfig_list_longValue() { + Map config = new HashMap<>(); + config.put("key", Collections.singletonList(3L)); + + builder.defaultServiceConfig(config); + + assertThat(builder.defaultServiceConfig).containsExactlyEntriesIn(config); } @Test