Skip to content

Commit b7d90f9

Browse files
validate extra params conflict
1 parent ed1a19e commit b7d90f9

File tree

2 files changed

+42
-7
lines changed

2 files changed

+42
-7
lines changed

src/main/java/com/stripe/net/ApiRequestParamsConverter.java

+27-7
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
import com.google.gson.stream.JsonWriter;
1313

1414
import com.stripe.Stripe;
15-
1615
import com.stripe.param.common.EmptyParam;
16+
1717
import java.io.IOException;
1818
import java.util.Map;
1919

@@ -32,30 +32,50 @@ public void deserializeAndTransform(Map<String, Object> outerMap,
3232
Map.Entry<String, JsonElement> jsonEntry,
3333
UntypedMapDeserializer untypedMapDeserializer) {
3434
String key = jsonEntry.getKey();
35-
JsonElement value = jsonEntry.getValue();
35+
JsonElement jsonValue = jsonEntry.getValue();
3636
if (ApiRequestParams.EXTRA_PARAMS_KEY.equals(key)) {
37-
if (!value.isJsonObject()) {
37+
if (!jsonValue.isJsonObject()) {
3838
throw new IllegalStateException(String.format(
3939
"Unexpected schema for extra params. JSON object is expected at key `%s`, but found"
4040
+ " `%s`. This is likely a problem with this current library version `%s`. "
4141
+ "Please contact [email protected] for assistance.",
42-
ApiRequestParams.EXTRA_PARAMS_KEY, value, Stripe.VERSION));
42+
ApiRequestParams.EXTRA_PARAMS_KEY, jsonValue, Stripe.VERSION));
4343
}
4444
// JSON value now corresponds to the extra params map, and is also deserialized as a map.
4545
// Instead of putting this result map under the original key, flatten the map
4646
// by adding all its key/value pairs to the outer map instead.
4747
Map<String, Object> extraParamsMap =
48-
untypedMapDeserializer.deserialize(value.getAsJsonObject());
49-
outerMap.putAll(extraParamsMap);
48+
untypedMapDeserializer.deserialize(jsonValue.getAsJsonObject());
49+
for (Map.Entry<String, Object> entry : extraParamsMap.entrySet()) {
50+
validateDuplicateKey(outerMap, entry.getKey(), entry.getValue());
51+
outerMap.put(entry.getKey(), entry.getValue());
52+
}
5053
} else {
54+
Object value = untypedMapDeserializer.deserializeJsonElement(jsonValue);
55+
validateDuplicateKey(outerMap, key, value);
56+
5157
// Normal deserialization where output map has the same structure as the given JSON content.
5258
// The deserialized content is an untyped `Object` and added to the outer map at the
5359
// original key.
54-
outerMap.put(key, untypedMapDeserializer.deserializeJsonElement(value));
60+
outerMap.put(key, value);
5561
}
5662
}
5763
}
5864

65+
private static void validateDuplicateKey(Map<String, Object> outerMap,
66+
String paramKey, Object paramValue) {
67+
if (outerMap.containsKey(paramKey)) {
68+
throw new IllegalArgumentException(String.format(
69+
"Found multiple param values for the same param key. This can happen because you passed "
70+
+ "additional parameters via `putExtraParam` that conflict with the existing params. "
71+
+ "Found param key `%s` with values `%s` and `%s`. "
72+
+ "If you wish to pass additional params for nested parameters, you "
73+
+ "should add extra params at the nested params themselves, not from the "
74+
+ "top-level param.",
75+
paramKey, outerMap.get(paramKey), paramValue));
76+
}
77+
}
78+
5979
/**
6080
* Type adapter to convert an empty enum to null value to comply with the lower-lever encoding
6181
* logic for the API request parameters.

src/test/java/com/stripe/net/ApiRequestParamsConverterTest.java

+15
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,21 @@ public void testIllegalExtraParamsType() {
195195
assertTrue(exception.getMessage().contains("Unexpected schema for extra params"));
196196
}
197197

198+
@Test
199+
public void testIllegalConflictingExtraParams() {
200+
ModelHasExtraParams fooParams = new ModelHasExtraParams(ParamCode.ENUM_FOO);
201+
// `string_value` will find two param values: one from the original param, the other from the
202+
// flattened extra param map.
203+
assertTrue(fooParams.toMap().containsKey("string_value"));
204+
fooParams.extraParams.put("string_value", "my conflicting param value");
205+
206+
IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> {
207+
toMap(fooParams);
208+
});
209+
assertTrue(exception.getMessage().contains(
210+
"Found param key `string_value` with values `foo` and `my conflicting param value`."));
211+
}
212+
198213
private Map<String, Object> toMap(ApiRequestParams params) {
199214
return converter.convert(params);
200215
}

0 commit comments

Comments
 (0)