android - Gson 日期反序列化失败

标签 android date gson

几个小时以来我一直在拉头发。

我在 android 项目中使用 Gson 2.2.4 (api ver 21 (android 5.0))。

我正在使用在 nodejs/typescript 中编写的应用程序作为后端,该后端为 android 客户端序列化 json 数据。

在安卓客户端我这样做:

Gson gs = new GsonBuilder()
        .setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
        .create();
Type listType = new TypeToken<ArrayList<Recording>>(){}.getType();
final ArrayList<Recording> schedule = gs.fromJson(args[0].toString(), listType);

序列化类:

录音:

package net.misove.mypvrcommon.entities;

/**
 * Created by mhainc on 2/10/2016.
 */
public class Recording {
    public Recording(EPGItem epgItem, String channelName) {
        this.epgItem = epgItem;
        this.channelName = channelName;
    }

    public EPGItem getEpgItem() {
        return epgItem;
    }

    private EPGItem epgItem;

    public String getChannelName() {
        return channelName;
    }

    public void setChannelName(String channelName) {
        this.channelName = channelName;
    }

    private String channelName;
}

EPGI项目:

package net.misove.mypvrcommon.entities;

import net.misove.mypvrcommon.util.Helpers;

import org.simpleframework.xml.Element;
import org.simpleframework.xml.Root;

import java.sql.Time;
import java.util.Calendar;
import java.util.Date;

/**
 * Created by mhainc on 2/9/2016.
 */
@Root(name="programme",strict = false)
public class EPGItem {
    @Element(name="id", required = false)
    private Integer id;
    @Element(name="name", required = false)
    private String name;
    @Element(name="premiere", required = false)
    private Integer premiere;
    @Element(name="widescreen", required = false)
    private Integer widescreen;
    @Element(name="stereo", required = false)
    private Integer stereo;
    @Element(name="blackWhite", required = false)
    private Integer blackWhite;
    @Element(name="subtitles", required = false)
    private Integer subtitles;
    @Element(name="hd", required = false)
    private Integer hd;
    @Element(name="shortDescription", required = false)
    private String shortDescription;
    @Element(name="longDescription", required = false)
    private String longDescription;
    @Element(name="series", required = false)
    private Integer series;
    @Element(name="seriesId", required = false)
    private Integer seriesId;
    @Element(name="origin", required = false)
    private String origin;
    //actors
    //directors
    @Element(name="duration", required = false)
    private Integer duration;
    @Element(name="date", required = false)
    private Date date;
    @Element(name="dateTimeInSec", required = false)
    private int dateTimeInSec;
    @Element(name="startDate", required = false)
    private Date startDate;
    @Element(name="startDateTimeInSec", required = false)
    private int startDateTimeInSec;
    @Element(name="startTime", required = false)
    private Time startTime;
    @Element(name="endDate", required = false)
    private Date endDate;
    @Element(name="endDateTimeInSec", required = false)
    private int endDateTimeInSec;
    @Element(name="endTime", required = false)
    private Time endTime;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getPremiere() {
        return premiere;
    }

    public void setPremiere(Integer premiere) {
        this.premiere = premiere;
    }

    public Integer getWidescreen() {
        return widescreen;
    }

    public void setWidescreen(Integer widescreen) {
        this.widescreen = widescreen;
    }

    public Integer getStereo() {
        return stereo;
    }

    public void setStereo(Integer stereo) {
        this.stereo = stereo;
    }

    public Integer getBlackWhite() {
        return blackWhite;
    }

    public void setBlackWhite(Integer blackWhite) {
        this.blackWhite = blackWhite;
    }

    public Integer getSubtitles() {
        return subtitles;
    }

    public void setSubtitles(Integer subtitles) {
        this.subtitles = subtitles;
    }

    public Integer getHd() {
        return hd;
    }

    public void setHd(Integer hd) {
        this.hd = hd;
    }

    public String getShortDescription() {
        return shortDescription;
    }

    public void setShortDescription(String shortDescription) {
        this.shortDescription = shortDescription;
    }

    public String getLongDescription() {
        return longDescription;
    }

    public void setLongDescription(String longDescription) {
        this.longDescription = longDescription;
    }

    public Integer getSeries() {
        return series;
    }

    public void setSeries(Integer series) {
        this.series = series;
    }

    public Integer getSeriesId() {
        return seriesId;
    }

    public void setSeriesId(Integer seriesId) {
        this.seriesId = seriesId;
    }

    public String getOrigin() {
        return origin;
    }

    public void setOrigin(String origin) {
        this.origin = origin;
    }

    public Integer getDuration() {
        return duration;
    }

    public void setDuration(Integer duration) {
        this.duration = duration;
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    public int getDateTimeInSec() {
        return dateTimeInSec;
    }

    public void setDateTimeInSec(int dateTimeInSec) {
        this.dateTimeInSec = dateTimeInSec;
    }

    public Date getStartDate() {
        return startDate;
    }

    public void setStartDate(Date startDate) {
        this.startDate = startDate;
    }

    public int getStartDateTimeInSec() {
        return startDateTimeInSec;
    }

    public void setStartDateTimeInSec(int startDateTimeInSec) {
        this.startDateTimeInSec = startDateTimeInSec;
    }

    public Time getStartTime() {
        return startTime;
    }

    public void setStartTime(Time startTime) {
        this.startTime = startTime;
    }

    public Date getEndDate() {
        return endDate;
    }

    public void setEndDate(Date endDate) {
        this.endDate = endDate;
    }

    public int getEndDateTimeInSec() {
        return endDateTimeInSec;
    }

    public void setEndDateTimeInSec(int endDateTimeInSec) {
        this.endDateTimeInSec = endDateTimeInSec;
    }

    public Time getEndTime() {
        return endTime;
    }

    public void setEndTime(Time endTime) {
        this.endTime = endTime;
    }
    //pictures
    //programme-type

    public Date getStartDateTime(Calendar cal)
    {
        cal.setTime(new Date(0));
        cal.add(Calendar.SECOND, getStartDateTimeInSec());
        /*
        Date date = getDate();
        cal.setTime(date);
        cal.add(Calendar.HOUR, startTime.getHours());
        cal.add(Calendar.MINUTE, startTime.getMinutes());
        */
        Date startDate = cal.getTime();
        return startDate;
    }

    public Date getEndDateTime(Calendar cal)
    {
        cal.setTime(new Date(0));
        cal.add(Calendar.SECOND, getEndDateTimeInSec());
        /*
        cal.setTime(date);
        cal.add(Calendar.HOUR, endTime.getHours());
        cal.add(Calendar.MINUTE, endTime.getMinutes());
        */
        Date endDate = cal.getTime();
        return endDate;
    }



    public int getProgress()
    {
        Date nowDt = new Date();
        long now = nowDt.getTime();
        Calendar cal = Helpers.getCalendar();
        long start = getStartDateTime(cal).getTime();
        long end = getEndDateTime(cal).getTime();

        long duration = Math.abs(end - start);
        long played = now - start;

        float onepercent = (float)duration / (float)100;
        float percentplayed =  (float)played / onepercent;
        return Math.round(percentplayed);
    }

}

变量args[0].toString() JSON内容为:

[{
    "epgItem": {
        "name": "Jak svet stvoril Ameriku",
        "date": "2017-08-31T22:00:00.000Z",
        "startTime": "2017-09-01T19:00:00.000Z",
        "endTime": "2017-09-01T21:00:00.000Z"
    },
    "channelName": "History HD"
}]

当反序列化器命中任何日期字段时,我收到此异常:

com.google.gson.JsonSyntaxException: java.text.ParseException: Unparseable date: "2017-09-01T19:00:00.000Z" (at offset 4)
at com.google.gson.internal.bind.TimeTypeAdapter.read(TimeTypeAdapter.java:59)
at com.google.gson.internal.bind.TimeTypeAdapter.read(TimeTypeAdapter.java:40)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:93)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:172)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:93)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:172)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:40)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:81)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:60)
at com.google.gson.Gson.fromJson(Gson.java:803)
at com.google.gson.Gson.fromJson(Gson.java:768)
at com.google.gson.Gson.fromJson(Gson.java:717)
at net.misove.mypvr.ScheduleViewActivity$2.call(ScheduleViewActivity.java:61)
at com.github.nkzawa.emitter.Emitter.emit(Emitter.java:117)
at com.github.nkzawa.socketio.client.Socket.onevent(Socket.java:308)
at com.github.nkzawa.socketio.client.Socket.onpacket(Socket.java:272)
at com.github.nkzawa.socketio.client.Socket.access$100(Socket.java:18)
at com.github.nkzawa.socketio.client.Socket$2$2.call(Socket.java:99)
at com.github.nkzawa.emitter.Emitter.emit(Emitter.java:117)
at com.github.nkzawa.socketio.client.Manager.ondecoded(Manager.java:347)
at com.github.nkzawa.socketio.client.Manager.access$1300(Manager.java:19)
at com.github.nkzawa.socketio.client.Manager$3.call(Manager.java:321)
at com.github.nkzawa.emitter.Emitter.emit(Emitter.java:117)
at com.github.nkzawa.socketio.parser.Parser$Decoder.add(Parser.java:156)
at com.github.nkzawa.socketio.client.Manager.ondata(Manager.java:339)
at com.github.nkzawa.socketio.client.Manager.access$1100(Manager.java:19)
at com.github.nkzawa.socketio.client.Manager$2.call(Manager.java:312)
at com.github.nkzawa.emitter.Emitter.emit(Emitter.java:117)
at com.github.nkzawa.engineio.client.Socket.onPacket(Socket.java:482)
at com.github.nkzawa.engineio.client.Socket.access$800(Socket.java:29)
at com.github.nkzawa.engineio.client.Socket$5.call(Socket.java:285)
at com.github.nkzawa.emitter.Emitter.emit(Emitter.java:117)
at com.github.nkzawa.engineio.client.Transport.onPacket(Transport.java:121)
at com.github.nkzawa.engineio.client.Transport.onData(Transport.java:113)
at com.github.nkzawa.engineio.client.transports.WebSocket.access$100(WebSocket.java:19)
at com.github.nkzawa.engineio.client.transports.WebSocket$1$3.run(WebSocket.java:74)
at com.github.nkzawa.thread.EventThread$2.run(EventThread.java:75)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
Caused by: java.text.ParseException: Unparseable date: "2017-09-01T19:00:00.000Z" (at offset 4)
at java.text.DateFormat.parse(DateFormat.java:579)
at com.google.gson.internal.bind.TimeTypeAdapter.read(TimeTypeAdapter.java:56)
at com.google.gson.internal.bind.TimeTypeAdapter.read(TimeTypeAdapter.java:40) 
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:93) 
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:172) 
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:93) 
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:172) 
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:40) 
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:81) 
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:60) 
at com.google.gson.Gson.fromJson(Gson.java:803) 
at com.google.gson.Gson.fromJson(Gson.java:768) 
at com.google.gson.Gson.fromJson(Gson.java:717) 
at net.misove.mypvr.ScheduleViewActivity$2.call(ScheduleViewActivity.java:61) 
at com.github.nkzawa.emitter.Emitter.emit(Emitter.java:117) 
at com.github.nkzawa.socketio.client.Socket.onevent(Socket.java:308) 
at com.github.nkzawa.socketio.client.Socket.onpacket(Socket.java:272) 
at com.github.nkzawa.socketio.client.Socket.access$100(Socket.java:18) 
at com.github.nkzawa.socketio.client.Socket$2$2.call(Socket.java:99) 
at com.github.nkzawa.emitter.Emitter.emit(Emitter.java:117) 
at com.github.nkzawa.socketio.client.Manager.ondecoded(Manager.java:347) 
at com.github.nkzawa.socketio.client.Manager.access$1300(Manager.java:19) 
at com.github.nkzawa.socketio.client.Manager$3.call(Manager.java:321) 
at com.github.nkzawa.emitter.Emitter.emit(Emitter.java:117) 
at com.github.nkzawa.socketio.parser.Parser$Decoder.add(Parser.java:156) 
at com.github.nkzawa.socketio.client.Manager.ondata(Manager.java:339) 
at com.github.nkzawa.socketio.client.Manager.access$1100(Manager.java:19) 
at com.github.nkzawa.socketio.client.Manager$2.call(Manager.java:312) 
at com.github.nkzawa.emitter.Emitter.emit(Emitter.java:117) 
at com.github.nkzawa.engineio.client.Socket.onPacket(Socket.java:482) 
at com.github.nkzawa.engineio.client.Socket.access$800(Socket.java:29) 
at com.github.nkzawa.engineio.client.Socket$5.call(Socket.java:285) 
at com.github.nkzawa.emitter.Emitter.emit(Emitter.java:117) 
at com.github.nkzawa.engineio.client.Transport.onPacket(Transport.java:121) 
at com.github.nkzawa.engineio.client.Transport.onData(Transport.java:113) 
at com.github.nkzawa.engineio.client.transports.WebSocket.access$100(WebSocket.java:19) 
at com.github.nkzawa.engineio.client.transports.WebSocket$1$3.run(WebSocket.java:74) 
at com.github.nkzawa.thread.EventThread$2.run(EventThread.java:75) 
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) 
at java.lang.Thread.run(Thread.java:818) 

我特别想知道错误消息中的“(偏移量为 4)”是什么...日期格式中的偏移量 4 是“-”,所以它在 J​​SON 的日期值中...我'我有点困惑,如果对此有任何见解,我将不胜感激。

我想尝试的一件事是为日期编写自己的类型反序列化适配器并将其插入 gson,但这对于简单的日期时间反序列化来说似乎太多了。

更新: “S A”在他的回答中提出的针对日期使用自己的反序列化适配器的方法也不起作用。抛出相同的异常。

最佳答案

我想我前段时间遇到过这样的问题。尝试像这样构建您的 gson 实例:

new GsonBuilder()
 .registerTypeAdapter(Date.class, new ISO8601DateAdapter())
 .setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
 .create();

这里有类:

ISO8601DateAdapter.java

ISO8601DateParser.java

ISO8601TimeAdapter.java

让我知道这是否有效。

关于android - Gson 日期反序列化失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46004515/

相关文章:

android - 解析一个json文件

java - 加快日期模式匹配速度

java - 从java中的响应复杂json中提取所有值

kotlin - 使用@field :SerializedName annotation instead of @SerializedName?的目的是什么

java - 使用GSON将JSON数据转换为Java对象(包括Object类)

java - 如何在onResume内判断设备是否已从 sleep 模式唤醒

android - on"XYZ"回调事件如何工作?

Android 深度链接两个单独的 Activity

javascript - 为什么 JSON.stringify() 接受 Date 对象?

python - 如何在Python中获取季度开始日期