retrofit.RetrofitError: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1

retrofit.RetrofitError: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1

我得到一个非常奇怪的 json 如下所示,gson 无法以任何方式解析它。我试图将它捕获为列表,因为它看起来是一个数组,但总是在

上方抛出异常
[{"Old":"1","New":"2","ConfirmNew":"2","Result":"succesfully completed","CustomProperties":{}},"eyJBY2Nlc3NUb2tlbiI6bnVsbCwiQ3VzdG9tZXJJRCI6NTc0Njc1LCJMYXN0QWNjZXNzVGltZSI6IlwvRGF0ZSgxNDQ3MzcyMjY3NjgxKVwvIiwiU2Vzc2lvbkd1aWQiOiIwZTkyNTY0YS05NzI1LTQ2MWEtOTMyYS03OTczZmMyYWJhN2QifQ=="]

这是我要解析的 class

@Getter
@Setter
@Accessors(fluent = true)
public class ChangePasswordResponseEntity {


@Expose
@SerializedName("Old")
private String Old;
@Expose
@SerializedName("New")
private String New;
@Expose
@SerializedName("ConfirmNew")
private String ConfirmNew;
@Expose
@SerializedName("Result")
private String Result;
@Expose
@SerializedName("CustomProperties")
private CustomProperties CustomProperties;
}

和改装方面

@POST("/ChangePassword/")
    Observable<List<ChangePasswordResponseEntity>> changePassword(
            @Body ChangePasswordRequestEntity changePasswordRequestEntity,
            @Query(value = "signedRequest", encodeValue = false) String sessionID);

您似乎在错误消息变得有趣的地方截断了错误消息,即第 1 行中解析失败的字符位置。我的猜测是位置是96+-1.

[
    {
        "Old": "1",
        "New": "2",
        "ConfirmNew": "2",
        "Result": "succesfully completed",
        "CustomProperties": {}
    },
    "eyJBY2Nlc3NUb2tlbiI6bnVsbCwiQ3VzdG9tZXJJRCI6NTc0Njc1LCJMYXN0QWNjZXNzVGltZSI6IlwvRGF0ZSgxNDQ3MzcyMjY3NjgxKVwvIiwiU2Vzc2lvbkd1aWQiOiIwZTkyNTY0YS05NzI1LTQ2MWEtOTMyYS03OTczZmMyYWJhN2QifQ=="
]

我想解析失败不是因为第一个元素,它确实是一个对象并且确实适合你的ChangePasswordResponseEntity,而是因为第二个元素,它是一个字符串。

您可以自定义 TypeAdapterFactory。获取数组的第一个元素并丢弃其余元素。

public class PasswordResponseAdapterFactory implements TypeAdapterFactory {
  @Override
  public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
    if (typeToken.getType() != ChangePasswordResponseEntity.class) {
      return null;
    }
    return (TypeAdapter<T>) newPasswordResponseAdapter(gson.getDelegateAdapter(this, TypeToken.get(ChangePasswordResponseEntity.class)));
  }

  private  TypeAdapter<ChangePasswordResponseEntity> newPasswordResponseAdapter (final TypeAdapter<ChangePasswordResponseEntity> delegateAdapter) {
    return new TypeAdapter<ChangePasswordResponseEntity>() {

      @Override
      public void write(JsonWriter out, ChangePasswordResponseEntity value) throws IOException {
        delegateAdapter.write(out, value);
      }

      @Override
      public ChangePasswordResponseEntity read(JsonReader in) throws IOException {
        in.beginArray();
        ChangePasswordResponseEntity response = delegateAdapter.read(in);
        while(in.hasNext()) {
          // Skip remaining elements in the array
          in.skipValue();
        }
        in.endArray();
        return response;
      }
    };
  }
}

更改您的界面以仅查找 ChangePasswordResponseEntity --

@POST("/ChangePassword/")
    Observable<ChangePasswordResponseEntity> changePassword(
            @Body ChangePasswordRequestEntity changePasswordRequestEntity,
            @Query(value = "signedRequest", encodeValue = false) String sessionID);

与您的工厂一起制作自定义 gson --

Gson gson = new GsonBuilder()
    .registerTypeAdapterFactory(new PasswordResponseAdapterFactory())
    .create();

创建 GsonConverterFactory 时使用新的 gson。

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("http://www.example.com/")
    .addConverterFactory(GsonConverterFactory.create(gson))
    // other settings ...
    .build();