Skip to content

Commit 6a30e75

Browse files
mbroshi-stripeclauderamya-stripe
authored
Update v2 array parameter serialization to use indexed format (#2110)
* Update v2 array parameter serialization to use indexed format Change array parameter serialization for v2 endpoints to use indexed format (e.g., ?include[0]=foo&include[1]=bar) instead of the repeated parameter format (e.g., ?include=foo&include=bar). This aligns v2 behavior with v1 for consistency. Changes: - Modified FormEncoder.java flattenParamsCollection to always use indexed format - Updated tests to expect indexed format for v2 arrays 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> Committed-By-Agent: claude * Remove references to arraysAsRepeated * Format code * Remove deprecated function * Fix formatting --------- Co-authored-by: Claude <[email protected]> Co-authored-by: Ramya Rao <[email protected]>
1 parent db05641 commit 6a30e75

File tree

3 files changed

+25
-52
lines changed

3 files changed

+25
-52
lines changed

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

Lines changed: 15 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public static HttpContent createHttpContent(Map<String, Object> params) throws I
2222
return HttpContent.buildFormURLEncodedContent(new ArrayList<KeyValuePair<String, String>>());
2323
}
2424

25-
Collection<KeyValuePair<String, Object>> flatParams = flattenParams(params, false);
25+
Collection<KeyValuePair<String, Object>> flatParams = flattenParams(params);
2626

2727
// If all parameters have been encoded as strings, then the content can be represented
2828
// with application/x-www-form-url-encoded encoding. Otherwise, use
@@ -46,24 +46,12 @@ public static HttpContent createHttpContent(Map<String, Object> params) throws I
4646
* @return The query string.
4747
*/
4848
public static String createQueryString(Map<String, Object> params) {
49-
return FormEncoder.createQueryString(params, false);
50-
}
51-
52-
/**
53-
* Creates the HTTP query string for a given map of parameters.
54-
*
55-
* @param params The map of parameters.
56-
* @param arraysAsRepeated Whether to encode arrays as repeated value ({@code a=1&a=2}) defaults
57-
* to brackets encoding ({@code a[]=1,2}).
58-
* @return The query string.
59-
*/
60-
public static String createQueryString(Map<String, Object> params, boolean arraysAsRepeated) {
6149
if (params == null) {
6250
return "";
6351
}
6452

6553
Collection<KeyValuePair<String, String>> flatParams =
66-
flattenParams(params, arraysAsRepeated).stream()
54+
flattenParams(params).stream()
6755
.filter(kvp -> kvp.getValue() instanceof String)
6856
.map(kvp -> new KeyValuePair<String, String>(kvp.getKey(), (String) kvp.getValue()))
6957
.collect(Collectors.toList());
@@ -117,13 +105,10 @@ public static String createQueryString(
117105
* }</pre>
118106
*
119107
* @param params The map of parameters.
120-
* @param arraysAsRepeated Whether to encode arrays as repeated value ({@code a=1&a=2}) defaults
121-
* to brackets encoding ({@code a[]=1,2}).
122108
* @return The flattened list of parameters.
123109
*/
124-
public static List<KeyValuePair<String, Object>> flattenParams(
125-
Map<String, Object> params, boolean arraysAsRepeated) {
126-
return flattenParamsValue(params, null, arraysAsRepeated);
110+
public static List<KeyValuePair<String, Object>> flattenParams(Map<String, Object> params) {
111+
return flattenParamsValue(params, null);
127112
}
128113

129114
/**
@@ -157,12 +142,10 @@ private static String urlEncode(String value) {
157142
*
158143
* @param value The value for which to create the list of parameters.
159144
* @param keyPrefix The key under which new keys should be nested, if any.
160-
* @param arraysAsRepeated Whether to encode arrays as repeated value ({@code a=1&a=2}) defaults
161-
* to brackets encoding ({@code a[]=1,2}).
162145
* @return The list of parameters.
163146
*/
164147
private static List<KeyValuePair<String, Object>> flattenParamsValue(
165-
Object value, String keyPrefix, boolean arraysAsRepeated) {
148+
Object value, String keyPrefix) {
166149
List<KeyValuePair<String, Object>> flatParams = null;
167150

168151
// I wish Java had pattern matching :(
@@ -171,7 +154,7 @@ private static List<KeyValuePair<String, Object>> flattenParamsValue(
171154
flatParams = singleParam(keyPrefix, "");
172155

173156
} else if (value instanceof Map<?, ?>) {
174-
flatParams = flattenParamsMap((Map<?, ?>) value, keyPrefix, arraysAsRepeated);
157+
flatParams = flattenParamsMap((Map<?, ?>) value, keyPrefix);
175158

176159
} else if (value instanceof String) {
177160
flatParams = singleParam(keyPrefix, value);
@@ -183,12 +166,12 @@ private static List<KeyValuePair<String, Object>> flattenParamsValue(
183166
flatParams = singleParam(keyPrefix, value);
184167

185168
} else if (value instanceof Collection<?>) {
186-
flatParams = flattenParamsCollection((Collection<?>) value, keyPrefix, arraysAsRepeated);
169+
flatParams = flattenParamsCollection((Collection<?>) value, keyPrefix);
187170

188171
} else if (value.getClass().isArray()) {
189172
Object[] array = getArrayForObject(value);
190173
Collection<?> collection = Arrays.stream(array).collect(Collectors.toList());
191-
flatParams = flattenParamsCollection(collection, keyPrefix, arraysAsRepeated);
174+
flatParams = flattenParamsCollection(collection, keyPrefix);
192175

193176
} else if (value.getClass().isEnum()) {
194177
flatParams =
@@ -211,7 +194,7 @@ private static List<KeyValuePair<String, Object>> flattenParamsValue(
211194
* @return The list of parameters.
212195
*/
213196
private static List<KeyValuePair<String, Object>> flattenParamsMap(
214-
Map<?, ?> map, String keyPrefix, boolean arraysAsRepeated) {
197+
Map<?, ?> map, String keyPrefix) {
215198
List<KeyValuePair<String, Object>> flatParams = new ArrayList<KeyValuePair<String, Object>>();
216199
if (map == null) {
217200
return flatParams;
@@ -223,7 +206,7 @@ private static List<KeyValuePair<String, Object>> flattenParamsMap(
223206

224207
String newPrefix = newPrefix(key, keyPrefix);
225208

226-
flatParams.addAll(flattenParamsValue(value, newPrefix, arraysAsRepeated));
209+
flatParams.addAll(flattenParamsValue(value, newPrefix));
227210
}
228211

229212
return flatParams;
@@ -236,28 +219,27 @@ private static List<KeyValuePair<String, Object>> flattenParamsMap(
236219
*
237220
* @param collection The collection for which to create the list of parameters.
238221
* @param keyPrefix The key under which new keys should be nested.
239-
* @param arraysAsRepeated Whether to encode arrays as repeated value ({@code a=1&a=2}) defaults
240-
* to brackets encoding ({@code a[]=1,2}).
241222
* @return The list of parameters.
242223
*/
243224
private static List<KeyValuePair<String, Object>> flattenParamsCollection(
244-
Collection<?> collection, String keyPrefix, boolean arraysAsRepeated) {
225+
Collection<?> collection, String keyPrefix) {
245226
List<KeyValuePair<String, Object>> flatParams = new ArrayList<KeyValuePair<String, Object>>();
246227
if (collection == null) {
247228
return flatParams;
248229
}
249230

250231
int index = 0;
251232
for (Object value : collection) {
252-
String newPrefix = arraysAsRepeated ? keyPrefix : String.format("%s[%d]", keyPrefix, index);
253-
flatParams.addAll(flattenParamsValue(value, newPrefix, arraysAsRepeated));
233+
// Always use indexed format for arrays
234+
String newPrefix = String.format("%s[%d]", keyPrefix, index);
235+
flatParams.addAll(flattenParamsValue(value, newPrefix));
254236
index += 1;
255237
}
256238

257239
/* Because application/x-www-form-urlencoded cannot represent an empty list, convention
258240
* is to take the list parameter and just set it to an empty string. (E.g. A regular
259241
* list might look like `a[0]=1&b[1]=2`. Emptying it would look like `a=`.) */
260-
if (!arraysAsRepeated && flatParams.isEmpty()) {
242+
if (flatParams.isEmpty()) {
261243
flatParams.add(new KeyValuePair<String, Object>(keyPrefix, ""));
262244
}
263245

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

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ private StripeRequest(
7171
this.params = (params != null) ? Collections.unmodifiableMap(params) : null;
7272
this.options = (options != null) ? options : RequestOptions.getDefault();
7373
this.method = method;
74-
this.url = buildURL(method, url, params, apiMode);
74+
this.url = buildURL(method, url, params);
7575
this.headers = buildHeaders(method, this.options, this.content, apiMode);
7676
this.apiMode = apiMode;
7777
} catch (IOException e) {
@@ -107,7 +107,7 @@ private StripeRequest(
107107
this.params = (params != null) ? Collections.unmodifiableMap(params) : null;
108108
this.options = options;
109109
this.method = method;
110-
this.url = buildURL(method, url, params, apiMode);
110+
this.url = buildURL(method, url, params);
111111
this.content = buildContent(method, params, apiMode);
112112
this.headers = buildHeaders(method, this.options, this.content, apiMode);
113113
this.apiMode = apiMode;
@@ -219,7 +219,7 @@ public StripeRequest withAdditionalHeader(String name, String value) {
219219
}
220220

221221
private static URL buildURL(
222-
ApiResource.RequestMethod method, String spec, Map<String, Object> params, ApiMode apiMode)
222+
ApiResource.RequestMethod method, String spec, Map<String, Object> params)
223223
throws IOException {
224224
StringBuilder sb = new StringBuilder();
225225

@@ -229,8 +229,7 @@ private static URL buildURL(
229229
String specQueryString = specUrl.getQuery();
230230

231231
if ((method != ApiResource.RequestMethod.POST) && (params != null)) {
232-
String queryString =
233-
FormEncoder.createQueryString(params, apiMode == ApiMode.V2 ? true : false);
232+
String queryString = FormEncoder.createQueryString(params);
234233

235234
if (queryString != null && !queryString.isEmpty()) {
236235
if (specQueryString != null && !specQueryString.isEmpty()) {

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

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,8 @@
2626
import java.util.Map;
2727
import java.util.Set;
2828
import java.util.TreeSet;
29-
import javax.annotation.Nullable;
3029
import lombok.AllArgsConstructor;
3130
import lombok.Data;
32-
import lombok.RequiredArgsConstructor;
3331
import org.hamcrest.CoreMatchers;
3432
import org.junit.jupiter.api.Test;
3533

@@ -130,12 +128,10 @@ public void testCreateQueryString() {
130128
org.junit.Assume.assumeTrue(!System.getProperty("java.version").startsWith("10."));
131129

132130
@Data
133-
@RequiredArgsConstructor
134131
@AllArgsConstructor
135132
class TestCase {
136133
private final Map<String, Object> data;
137134
private final String want;
138-
@Nullable private Boolean arrayAsRepeated = false;
139135
}
140136

141137
List<TestCase> testCases =
@@ -376,18 +372,16 @@ class TestCase {
376372
"array", new Object[] {new String[] {"foo", "bar"}, new int[] {1, 2, 3}}),
377373
"array[0][0]=foo&array[0][1]=bar&array[1][0]=1&array[1][1]=2&array[1][2]=3"));
378374

379-
// Array (arrayAsRepeated)
380-
add(new TestCase(Collections.singletonMap("array", new String[] {}), "", true));
375+
// Array
376+
add(new TestCase(Collections.singletonMap("array", new String[] {}), "array="));
381377
add(
382378
new TestCase(
383379
Collections.singletonMap("array", new String[] {"1", "2", "3"}),
384-
"array=1&array=2&array=3",
385-
true));
380+
"array[0]=1&array[1]=2&array[2]=3"));
386381
add(
387382
new TestCase(
388383
Collections.singletonMap("array", new Object[] {123, "foo"}),
389-
"array=123&array=foo",
390-
true));
384+
"array[0]=123&array[1]=foo"));
391385
// Collection
392386
add(
393387
new TestCase(
@@ -429,9 +423,7 @@ class TestCase {
429423
};
430424

431425
for (TestCase testCase : testCases) {
432-
assertEquals(
433-
testCase.getWant(),
434-
FormEncoder.createQueryString(testCase.getData(), testCase.getArrayAsRepeated()));
426+
assertEquals(testCase.getWant(), FormEncoder.createQueryString(testCase.getData()));
435427
}
436428
}
437429

@@ -481,7 +473,7 @@ class TestCase {
481473
};
482474

483475
for (TestCase testCase : testCases) {
484-
assertEquals(testCase.getWant(), FormEncoder.flattenParams(testCase.getData(), false));
476+
assertEquals(testCase.getWant(), FormEncoder.flattenParams(testCase.getData()));
485477
}
486478
}
487479

0 commit comments

Comments
 (0)