【Android】Reading a NULL string not supported here. Expected BEGIN_OBJECT but was STRING...

问题描述

使用 Retrofit 发起网络请求时遇到了一个问题,控制台爆红,不断输出以下错误信息:

Parcel: Reading a NULL string not supported here.

【Android】Reading a NULL string not supported here. Expected BEGIN_OBJECT but was STRING..._第1张图片


原因分析

在处理 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 数据 createTimeupdateTime 上。这个错误通常表示 JSON 数据与代码预期的数据结构不符合。代码预期一个对象 (BEGIN_OBJECT),但实际上遇到了一个字符串 (STRING)。

【Android】Reading a NULL string not supported here. Expected BEGIN_OBJECT but was STRING..._第2张图片

【Android】Reading a NULL string not supported here. Expected BEGIN_OBJECT but was STRING..._第3张图片

由于 LocalDateTime 不是 Gson 默认支持的类型,所以需要使用自定义的适配器来解决这个问题。


解决方案

  1. 创建一个自定义的 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;
        }
    }
}

  1. 创建 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();

    }
}
  1. 在需要创建 Retrofit 实例的地方直接调用 RetrofitBuilder 的 build 静态方法即可。
 String baseUrl = getString(R.string.base_url);
 retrofit = RetrofitBuilder.build(baseUrl);

经过以上处理,问题得到解决,Retrofit 不再报错,而且可以正常获取到 createTime 和 updateTime 的数据。

你可能感兴趣的:(Android,android)