Retrofit 是一个用于 Android 和 Java 的 RESTful HTTP 客户端库,它简化了与 Web 服务的交互。Moshi 是一个现代的 JSON 库,用于在 Java 中解析和生成 JSON 数据。Retrofit 使用转换器(Converter)将数据在 Java 对象和 JSON 之间进行转换。
在使用 Retrofit 和 Moshi 时,可能会遇到 java.util.HashMap
无法被转换为 @Body
的问题。这是因为 Moshi 默认情况下不支持 HashMap
的转换。
Moshi 默认情况下不支持 HashMap
的转换,因为它不知道如何将 HashMap
转换为 JSON 或从 JSON 转换回 HashMap
。
JsonAdapter
你可以创建一个自定义的 JsonAdapter
来处理 HashMap
的转换。
import com.squareup.moshi.*;
import retrofit2.Retrofit;
import retrofit2.converter.moshi.MoshiConverterFactory;
import java.lang.reflect.Type;
import java.util.HashMap;
public class Main {
public static void main(String[] args) {
Moshi moshi = new Moshi.Builder()
.add(new HashMapAdapter())
.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.example.com/")
.addConverterFactory(MoshiConverterFactory.create(moshi))
.build();
// 继续使用 retrofit 进行 API 调用
}
static class HashMapAdapter {
@FromJson
public HashMap<String, Object> fromJson(JsonReader reader) throws IOException {
HashMap<String, Object> map = new HashMap<>();
reader.beginObject();
while (reader.hasNext()) {
String key = reader.nextName();
Object value = readJsonValue(reader);
map.put(key, value);
}
reader.endObject();
return map;
}
@ToJson
public void toJson(JsonWriter writer, HashMap<String, Object> map) throws IOException {
writer.beginObject();
for (HashMap.Entry<String, Object> entry : map.entrySet()) {
writer.name(entry.getKey());
writeJsonValue(writer, entry.getValue());
}
writer.endObject();
}
private Object readJsonValue(JsonReader reader) throws IOException {
switch (reader.peek()) {
case STRING:
return reader.nextString();
case NUMBER:
return reader.nextDouble();
case BOOLEAN:
return reader.nextBoolean();
case NULL:
reader.nextNull();
return null;
case BEGIN_OBJECT:
return readJsonObject(reader);
case BEGIN_ARRAY:
return readJsonArray(reader);
default:
throw new IllegalStateException("Unexpected value: " + reader.peek());
}
}
private void writeJsonValue(JsonWriter writer, Object value) throws IOException {
if (value == null) {
writer.nullValue();
} else if (value instanceof String) {
writer.value((String) value);
} else if (value instanceof Number) {
writer.value(((Number) value).doubleValue());
} else if (value instanceof Boolean) {
writer.value((Boolean) value);
} else if (value instanceof HashMap) {
writeJsonObject(writer, (HashMap<String, Object>) value);
} else if (value instanceof Iterable) {
writeJsonArray(writer, (Iterable<?>) value);
} else {
throw new IllegalArgumentException("Unsupported type: " + value.getClass());
}
}
private HashMap<String, Object> readJsonObject(JsonReader reader) throws IOException {
HashMap<String, Object> map = new HashMap<>();
reader.beginObject();
while (reader.hasNext()) {
String key = reader.nextName();
Object value = readJsonValue(reader);
map.put(key, value);
}
reader.endObject();
return map;
}
private void writeJsonObject(JsonWriter writer, HashMap<String, Object> map) throws IOException {
writer.beginObject();
for (HashMap.Entry<String, Object> entry : map.entrySet()) {
writer.name(entry.getKey());
writeJsonValue(writer, entry.getValue());
}
writer.endObject();
}
private ArrayList<Object> readJsonArray(JsonReader reader) throws IOException {
ArrayList<Object> list = new ArrayList<>();
reader.beginArray();
while (reader.hasNext()) {
Object value = readJsonValue(reader);
list.add(value);
}
reader.endArray();
return list;
}
private void writeJsonArray(JsonWriter writer, Iterable<?> array) throws IOException {
writer.beginArray();
for (Object item : array) {
writeJsonValue(writer, item);
}
writer.endArray();
}
}
}
@JsonClass(generateAdapter = true)
注解你可以创建一个包装类,并使用 @JsonClass(generateAdapter = true)
注解来生成适配器。
import com.squareup.moshi.JsonClass;
import com.squareup.moshi.Moshi;
import retrofit2.Retrofit;
import retrofit2.converter.moshi.MoshiConverterFactory;
import java.util.HashMap;
@JsonClass(generateAdapter = true)
public class MapWrapper {
public HashMap<String, Object> map;
public MapWrapper(HashMap<String, Object> map) {
this.map = map;
}
}
public class Main {
public static void main(String[] args) {
Moshi moshi = new Moshi.Builder().build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.example.com/")
.addConverterFactory(MoshiConverterFactory.create(moshi))
.build();
// 使用 MapWrapper 进行 API 调用
MapWrapper wrapper = new MapWrapper(new HashMap<>());
// 继续使用 retrofit 进行 API 调用
}
}
这种方法适用于需要将 HashMap
作为请求体发送到服务器的场景,例如动态构建请求参数时。
通过以上方法,你可以解决 Retrofit 和 Moshi 无法为 java.util.HashMap
创建 @Body
转换器的问题。
领取专属 10元无门槛券
手把手带您无忧上云