Skip to content

Commit b08fc78

Browse files
committed
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 grpc#12815
1 parent cc0d1a8 commit b08fc78

3 files changed

Lines changed: 49 additions & 15 deletions

File tree

core/src/main/java/io/grpc/internal/JsonUtil.java

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,8 @@ public static Double getNumberAsDouble(Map<String, ?> obj, String key) {
106106
return null;
107107
}
108108
Object value = obj.get(key);
109-
if (value instanceof Double) {
110-
return (Double) value;
109+
if (value instanceof Number) {
110+
return ((Number) value).doubleValue();
111111
}
112112
if (value instanceof String) {
113113
try {
@@ -132,8 +132,8 @@ public static Float getNumberAsFloat(Map<String, ?> obj, String key) {
132132
return null;
133133
}
134134
Object value = obj.get(key);
135-
if (value instanceof Float) {
136-
return (Float) value;
135+
if (value instanceof Number) {
136+
return ((Number) value).floatValue();
137137
}
138138
if (value instanceof String) {
139139
try {
@@ -159,11 +159,12 @@ public static Integer getNumberAsInteger(Map<String, ?> obj, String key) {
159159
return null;
160160
}
161161
Object value = obj.get(key);
162-
if (value instanceof Double) {
163-
Double d = (Double) value;
164-
int i = d.intValue();
162+
if (value instanceof Number) {
163+
Number n = (Number) value;
164+
double d = n.doubleValue();
165+
int i = n.intValue();
165166
if (i != d) {
166-
throw new ClassCastException("Number expected to be integer: " + d);
167+
throw new ClassCastException("Number expected to be integer: " + n);
167168
}
168169
return i;
169170
}
@@ -190,11 +191,12 @@ public static Long getNumberAsLong(Map<String, ?> obj, String key) {
190191
return null;
191192
}
192193
Object value = obj.get(key);
193-
if (value instanceof Double) {
194-
Double d = (Double) value;
195-
long l = d.longValue();
194+
if (value instanceof Number) {
195+
Number n = (Number) value;
196+
double d = n.doubleValue();
197+
long l = n.longValue();
196198
if (l != d) {
197-
throw new ClassCastException("Number expected to be long: " + d);
199+
throw new ClassCastException("Number expected to be long: " + n);
198200
}
199201
return l;
200202
}

core/src/main/java/io/grpc/internal/ManagedChannelImplBuilder.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -582,7 +582,7 @@ public ManagedChannelImplBuilder defaultServiceConfig(@Nullable Map<String, ?> s
582582
parsedMap.put(key, checkListEntryTypes((List<?>) value));
583583
} else if (value instanceof String) {
584584
parsedMap.put(key, value);
585-
} else if (value instanceof Double) {
585+
} else if (value instanceof Number) {
586586
parsedMap.put(key, value);
587587
} else if (value instanceof Boolean) {
588588
parsedMap.put(key, value);
@@ -606,7 +606,7 @@ private static List<?> checkListEntryTypes(List<?> list) {
606606
parsedList.add(checkListEntryTypes((List<?>) value));
607607
} else if (value instanceof String) {
608608
parsedList.add(value);
609-
} else if (value instanceof Double) {
609+
} else if (value instanceof Number) {
610610
parsedList.add(value);
611611
} else if (value instanceof Boolean) {
612612
parsedList.add(value);

core/src/test/java/io/grpc/internal/ManagedChannelImplBuilderTest.java

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -737,7 +737,39 @@ public void defaultServiceConfig_intValue() {
737737
Map<String, Object> config = new HashMap<>();
738738
config.put("key", 3);
739739

740-
assertThrows(IllegalArgumentException.class, () -> builder.defaultServiceConfig(config));
740+
builder.defaultServiceConfig(config);
741+
742+
assertThat(builder.defaultServiceConfig).containsExactlyEntriesIn(config);
743+
}
744+
745+
@Test
746+
public void defaultServiceConfig_longValue() {
747+
Map<String, Object> config = new HashMap<>();
748+
config.put("key", 3L);
749+
750+
builder.defaultServiceConfig(config);
751+
752+
assertThat(builder.defaultServiceConfig).containsExactlyEntriesIn(config);
753+
}
754+
755+
@Test
756+
public void defaultServiceConfig_list_intValue() {
757+
Map<String, Object> config = new HashMap<>();
758+
config.put("key", Collections.singletonList(3));
759+
760+
builder.defaultServiceConfig(config);
761+
762+
assertThat(builder.defaultServiceConfig).containsExactlyEntriesIn(config);
763+
}
764+
765+
@Test
766+
public void defaultServiceConfig_list_longValue() {
767+
Map<String, Object> config = new HashMap<>();
768+
config.put("key", Collections.singletonList(3L));
769+
770+
builder.defaultServiceConfig(config);
771+
772+
assertThat(builder.defaultServiceConfig).containsExactlyEntriesIn(config);
741773
}
742774

743775
@Test

0 commit comments

Comments
 (0)