问题描述
使用 Retrofit 发起网络请求时遇到了一个问题,控制台爆红,不断输出以下错误信息:
Parcel: Reading a NULL string not supported here.
原因分析
在处理 Retrofit 的请求回调中,使用 System.out.println(t.getMessage())
来打印异常信息。
@Override
public void onFailure(Call<Result<List<Animal>>> call, Throwable t) {
System.out.println(t.getMessage());
}
通过打印异常信息,发现以下错误:
java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 230 path $.data[0].updateTime
java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 195 path $.data[0].createTime
根据错误信息分析可知,问题出现在使用 Retrofit 结合 GsonConverterFactory 解析包含 LocalDateTime 类型的 JSON 数据 createTime
和 updateTime
上。这个错误通常表示 JSON 数据与代码预期的数据结构不符合。代码预期一个对象 (BEGIN_OBJECT),但实际上遇到了一个字符串 (STRING)。
由于 LocalDateTime 不是 Gson 默认支持的类型,所以需要使用自定义的适配器来解决这个问题。
解决方案
- 创建一个自定义的 Gson 适配器来处理 LocalDateTime 类型。这可以通过扩展 Gson 的 TypeAdapter 来实现。创建一个 LocalDateTimeAdapter 类。
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class LocalDateTimeAdapter extends TypeAdapter<LocalDateTime> {
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
@Override
public void write(JsonWriter out, LocalDateTime value) throws IOException {
if (value != null) {
out.value(FORMATTER.format(value));
} else {
out.nullValue();
}
}
@Override
public LocalDateTime read(JsonReader in) throws IOException {
if (in.hasNext()) {
String value = in.nextString();
return LocalDateTime.parse(value, FORMATTER);
} else {
return null;
}
}
}
- 创建 Retrofit 时,使用 GsonBuilder 将自定义的适配器注册到 Gson 中。可以创建一个 RetrofitBuilder 类,用于创建 Retrofit 实例。
import com.example.pawprint.adapter.LocalDateTimeAdapter;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.time.LocalDateTime;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class RetrofitBuilder {
public static Retrofit build(String baseUrl) {
// 创建 Gson 实例
Gson gson = new GsonBuilder()
.registerTypeAdapter(LocalDateTime.class, new LocalDateTimeAdapter())
.create();
// 创建 Retrofit 实例
return new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
}
}
- 在需要创建 Retrofit 实例的地方直接调用 RetrofitBuilder 的 build 静态方法即可。
String baseUrl = getString(R.string.base_url);
retrofit = RetrofitBuilder.build(baseUrl);
经过以上处理,问题得到解决,Retrofit 不再报错,而且可以正常获取到 createTime 和 updateTime 的数据。