Skip to content

Commit

Permalink
add suppport for multi-value map and test senario
Browse files Browse the repository at this point in the history
  • Loading branch information
zjc17 committed May 8, 2020
1 parent bcf07d0 commit f7dbf96
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 16 deletions.
68 changes: 52 additions & 16 deletions retrofit/src/main/java/retrofit2/ParameterHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
import java.io.IOException;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import javax.annotation.Nullable;
Expand Down Expand Up @@ -174,35 +176,69 @@ void apply(RequestBuilder builder, @Nullable Map<String, T> value) throws IOExce
throw Utils.parameterError(method, p, "Query map was null");
}

boolean fail = false;
String entryKey = null;
T entryValue = null;
for (Map.Entry<String, T> entry : value.entrySet()) {
String entryKey = entry.getKey();
entryKey = entry.getKey();
if (entryKey == null) {
throw Utils.parameterError(method, p, "Query map contained null key.");
}
T entryValue = entry.getValue();
entryValue = entry.getValue();
if (entryValue == null) {
throw Utils.parameterError(
method, p, "Query map contained null value for key '" + entryKey + "'.");
}

String convertedEntryValue = valueConverter.convert(entryValue);
String convertedEntryValue;
if (entryValue instanceof List || entryValue.getClass().isArray()) {
List<String> list = null;
if (entryValue.getClass().isArray()) {
throw new UnsupportedOperationException();
}
if (entryValue instanceof List) {
list = (List<String>)entryValue;
}
Iterator i = list.iterator();
if (!i.hasNext()) {
throw new IllegalArgumentException();
}
convertedEntryValue = valueConverter.convert((T)i.next());
if (convertedEntryValue == null) {
fail = true;
break;
} else {
builder.addQueryParam(entryKey, convertedEntryValue, encoded);
}
while (i.hasNext()) {
convertedEntryValue = valueConverter.convert((T)i.next());
if (convertedEntryValue == null) {
fail = true;
break;
} else {
builder.addQueryParam(entryKey, convertedEntryValue, encoded);
}
}
} else {
convertedEntryValue = valueConverter.convert(entryValue);
if (convertedEntryValue == null) {
throw Utils.parameterError(
method,
p,
"Query map value '"
+ entryValue
+ "' converted to null by "
+ valueConverter.getClass().getName()
+ " for key '"
+ entryKey
+ "'.");
fail = true;
break;
} else {
builder.addQueryParam(entryKey, convertedEntryValue, encoded);
}

builder.addQueryParam(entryKey, convertedEntryValue, encoded);
}
}
if (fail) {
throw Utils.parameterError(method, p, "Query map value '"
+ entryValue
+ "' converted to null by "
+ valueConverter.getClass().getName()
+ " for key '"
+ entryKey
+ "'.");
}
}
}

static final class HeaderMap<T> extends ParameterHandler<Map<String, T>> {
private final Method method;
Expand Down
41 changes: 41 additions & 0 deletions retrofit/src/test/java/retrofit2/RequestFactoryTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import java.lang.reflect.Method;
import java.math.BigInteger;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
Expand Down Expand Up @@ -1536,6 +1537,46 @@ Call<ResponseBody> method(@QueryMap(encoded = true) Map<String, Object> query) {
assertThat(request.body()).isNull();
}

@Test public void getWithQueryParamMultiValueMap() {
class Example {
@GET("/foo/bar/") //
Call<ResponseBody> method(@QueryMap(encoded = true) Map<String, Object> query) {
return null;
}
}
Map<String, Object> map = new HashMap<>();
List<String> param1 = new ArrayList<>();
param1.add("a");
param1.add("b");
map.put("string", param1);
Request request = buildRequest(Example.class, map);
assertThat(request.method()).isEqualTo("GET");
assertThat(request.headers().size()).isZero();
HttpUrl url = request.url();
assertThat(url.toString()).isEqualTo("http://example.com/foo/bar/?string=a&string=b");
assertThat(request.body()).isNull();
}

@Test public void getWithEncodedQueryParamMultiValueMap() {
class Example {
@GET("/foo/bar/") //
Call<ResponseBody> method(@QueryMap(encoded = true) Map<String, Object> query) {
return null;
}
}
Map<String, Object> map = new HashMap<>();
List<String> param1 = new ArrayList<>();
param1.add("a%20a");
param1.add("b%20b");
map.put("string", param1);
Request request = buildRequest(Example.class, map);
assertThat(request.method()).isEqualTo("GET");
assertThat(request.headers().size()).isZero();
HttpUrl url = request.url();
assertThat(url.toString()).isEqualTo("http://example.com/foo/bar/?string=a%20a&string=b%20b");
assertThat(request.body()).isNull();
}

@Test
public void getAbsoluteUrl() {
class Example {
Expand Down

0 comments on commit f7dbf96

Please sign in to comment.