首页 > 解决方案 > 解析时间戳期间的 GSON 异常

问题描述

由于时间戳格式,我的应用程序无法解析 REST API 响应。REST API 返回 JSON:

   {
        "id": 4,
        "username": "test555",
        "email": "test555@test.com",
        "password": "pass",
        "role": "USER",
        "enabled": 1,
        "lastPassChange": null,
        "created": [2019, 6, 16, 19, 8, 34, 843438000]
    }

但是我的应用程序抛出异常,因为它期待对象但它接收数组。

我添加了实现 'com.fatboyindustrial.gson-jodatime-serialisers:gson-jodatime-serialisers:1.7.0'

并添加到我的 gson 单例中:

public class GsonSingleton {
    private static GsonSingleton sInstace;
    private Gson gson;

    public static synchronized GsonSingleton getInstance(){
        if(sInstace == null){
            sInstace = new GsonSingleton();
        }
        return sInstace;
    }

    private GsonSingleton(){
        this.gson = Converters.registerLocalDateTime(new GsonBuilder()).create();
    }

    public Gson gson(){
        return this.gson;
    }

    public JSONObject obj2Json(Object o) throws JSONException{
        return new JSONObject(gson.toJson(o));
    }
} 

但这无济于事。

发生异常的行:

User savedUser = GsonSingleton.getInstance().gson().fromJson(response.toString(), User.class);

异常堆栈:

`com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 191 path $.created
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:226)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:131)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:222)
    at com.google.gson.Gson.fromJson(Gson.java:927)
    at com.google.gson.Gson.fromJson(Gson.java:892)
    at com.google.gson.Gson.fromJson(Gson.java:841)
    at com.google.gson.Gson.fromJson(Gson.java:813)
    at eu.blubit.autobook.view.AccountFormActivity$1.onResponse(AccountFormActivity.java:153)
    at eu.blubit.autobook.view.AccountFormActivity$1.onResponse(AccountFormActivity.java:148)
    at com.android.volley.toolbox.JsonRequest.deliverResponse(JsonRequest.java:90)
    at com.android.volley.ExecutorDelivery$ResponseDeliveryRunnable.run(ExecutorDelivery.java:102)
    at android.os.Handler.handleCallback(Handler.java:751)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:154)
    at android.app.ActivityThread.main(ActivityThread.java:6816)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1563)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1451)
 Caused by: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 191 path $.created
    at com.google.gson.stream.JsonReader.beginObject(JsonReader.java:385)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:215)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:131) 
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:222) 
    at com.google.gson.Gson.fromJson(Gson.java:927) 
    at com.google.gson.Gson.fromJson(Gson.java:892) 
    at com.google.gson.Gson.fromJson(Gson.java:841) 
    at com.google.gson.Gson.fromJson(Gson.java:813) 
    at eu.blubit.autobook.view.AccountFormActivity$1.onResponse(AccountFormActivity.java:153) 
    at eu.blubit.autobook.view.AccountFormActivity$1.onResponse(AccountFormActivity.java:148) 
    at com.android.volley.toolbox.JsonRequest.deliverResponse(JsonRequest.java:90) 
    at com.android.volley.ExecutorDelivery$ResponseDeliveryRunnable.run(ExecutorDelivery.java:102) 
    at android.os.Handler.handleCallback(Handler.java:751) 
    at android.os.Handler.dispatchMessage(Handler.java:95) 
    at android.os.Looper.loop(Looper.java:154) 
    at android.app.ActivityThread.main(ActivityThread.java:6816) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1563) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1451)`

但我应该收到 User.class 对象:

@Entity
public class User {

@PrimaryKey
@NonNull
private Long id;

@Size(min=3, max=20)
private String username;

private String email;

@Size(min=6)
private String password;

private String role;

private Integer enabled;

private LocalDateTime lastPassChange;

private LocalDateTime created;
//setters and getters

标签: androidtimestampgson

解决方案


我找到了其他适合我的方式。我在我的单例中添加了新类,它是 json 的自定义反序列化器。

public class JsonDateTimeArrayDeserializer implements JsonDeserializer<LocalDateTime>{
    @Override
    public LocalDateTime deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        JsonArray jArr = json.getAsJsonArray();
        return LocalDateTime.of(jArr.get(0).getAsInt(), jArr.get(1).getAsInt(), jArr.get(2).getAsInt(), jArr.get(3).getAsInt(), jArr.get(4).getAsInt(), jArr.get(5).getAsInt(), jArr.get(6).getAsInt());
    }
}

我必须在以下位置注册它private GsonSingleton()

this.gson = new GsonBuilder.registerTypeAdapter(LocalDateTime.class, new JsonDateTimeArrayDeserializer()).create

推荐阅读