美文网首页
DateTime系列化与返系列化,Json解析问题

DateTime系列化与返系列化,Json解析问题

作者: Darshan | 来源:发表于2019-05-24 17:26 被阅读0次

    前言

    目前,公司的项目app端与后台端通信时间采用的是DateTime类时间对象。这是一个第三方的时间类,转为字符串的时间格式为"2019-05-21T00:00:00+0800"。但是采用Gson转换时格式就不识别了,变成了这样:

    datetime to jsonStr = {"iChronology":{"iBase":{"iBase":{"iBase":{"iMinDaysInFirstWeek":4}},"iParam":
    
    {"iZone":{"iNameKeys":
    
    ["LMT","CST","CDT","CST","CDT","CST","CDT","CST","CDT","CST","CDT","CST","CDT","CST","CDT","CST","CDT","CST"
    
    ],"iStandardOffsets":
    
    [29143000,28800000,28800000,28800000,28800000,28800000,28800000,28800000,28800000,28800000,28800000,28800000
    
    ,28800000,28800000,28800000,28800000,28800000,28800000],"iTransitions":[-9223372036854775808,-
    
    2177481943000,-933494400000,-923130000000,-908784000000,-
    
    891594000000,515520000000,527007600000,545155200000,558457200000,576604800000,589906800000,608659200000,6219
    
    61200000,640108800000,653410800000,671558400000,684860400000],"iWallOffsets":
    
    [29143000,28800000,32400000,28800000,32400000,28800000,32400000,28800000,32400000,28800000,32400000,28800000
    
    ,32400000,28800000,32400000,28800000,32400000,28800000],"iID":"Asia/Shanghai"},"iID":"Asia/Shanghai"}}},"iMi
    
    llis":1558433492780}
    

    变成这样的格式既不是我们想要的,也变不回我们想要的DateTime。在做网络上传和数据保存在SharedPreferences中就遇到了很大的问题。

    Gson解析的原理

    Gson这个框架主要是为了解决java对象与json之间相互转换的。Gson提供了JsonDeserializer, JsonSerializer接口和TypeAdapter适配类来给对象做系列化和返系列化,如果不实现这些方法就会采用默认的方法。

    DateTime解析的解决办法

    既然Gson解析不识别DateTime,那我们可以实现Gson提供给我们的系列化和返系列化的方法自己做处理。这就有两种实现方法

    办法一

    Gson gson = new GsonBuilder().registerTypeAdapter(NoticeVo.class, new NoticeVoDataTimeAdapter()).create();
    

    首先设置Gson注册我们自己继承TypeAdapter实现的转换类,主要重写write(JsonWriter out, NoticeVo value)和read(JsonReader in) 方法。此实现类采用流的方式来实现系列化和返系列化。把我们需要转换的对象的属性一一转换,其中我们的关键属性DateTime就得做好转换的格式了。

    //系列化
    out.name("releaseDatetime").value(value.getReleaseDatetime().toString("yyyy-MM-dd'T'HH:mm:ssZ"));
    
    //返系列化
    vo.setReleaseDatetime(DateTime.parse(in.nextString()));
    

    NoticeVo对象的系列化和返系列化的适配类

    public class NoticeVoDataTimeAdapter extends TypeAdapter<NoticeVo> {
        @Override
        public void write(JsonWriter out, NoticeVo value) throws IOException {
    
            out.beginObject(); //流式序列化成对象开始
            out.name("description").value(value.getDescription());
            out.name("detailFileUrl").value(value.getDetailFileUrl());
            out.name("id").value(value.getId());
            out.name("introduction").value(value.getIntroduction());
            out.name("isRead").value(value.getIsRead());
            out.name("noticeTargetId").value(value.getNoticeTargetId());
            out.name("picPath").value(value.getPicPath());
            out.name("title").value(value.getTitle());
            out.name("releaseDatetime").value(value.getReleaseDatetime().toString("yyyy-MM-dd'T'HH:mm:ssZ"));
            out.endObject();
        }
    
        @Override
        public NoticeVo read(JsonReader in) throws IOException {
            in.beginObject();
            NoticeVo vo = new NoticeVo();
            while (in.hasNext()) {
                switch (in.nextName()) {
                    case "description":
                        vo.setDescription(in.nextString());
                        break;
                    case "detailFileUrl":
                        vo.setDetailFileUrl(in.nextString());
                        break;
                    case "id":
                        vo.setId(in.nextString());
                        break;
                    case "introduction":
                        vo.setIntroduction(in.nextString());
                        break;
                    case "isRead":
                        vo.setIsRead(in.nextBoolean());
                        break;
                    case "noticeTargetId":
                        vo.setNoticeTargetId(in.nextString());
                        break;
                    case "picPath":
                        vo.setPicPath(in.nextString());
                        break;
                    case "title":
                        vo.setTitle(in.nextString());
                        break;
                    case "releaseDatetime":
                        vo.setReleaseDatetime(DateTime.parse(in.nextString()));
                        break;
                }
            }
    
            in.endObject();
            return vo;
        }
    }
    
    

    办法二

    首先设置Gson注册我们自己实现 JsonDeserializer<DateTime>, JsonSerializer<DateTime>接口的转换类,在转换类里实现deserialize和serialize方法。

    new GsonBuilder()
                .setPrettyPrinting()
                .serializeNulls()
                .registerTypeAdapter(DateTime.class, new DateTimeSerializer())
                .create();
    
    /**
     * DateTime系列化与返系列化格式转换
     */
    
    public class DateTimeSerializer implements JsonDeserializer<DateTime>, JsonSerializer<DateTime> {
    
        private static DateTimeFormatter TIME_FORMAT = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ssZ");
    
        @Override
        public DateTime deserialize(final JsonElement je, final Type type,
                                    final JsonDeserializationContext jdc) throws JsonParseException {
            final String dateAsString = je.getAsString();
            if (dateAsString.length() == 0) {
                return null;
            } else {
                return DateTime.parse(dateAsString, TIME_FORMAT);
            }
        }
    
        @Override
        public JsonElement serialize(final DateTime src, final Type typeOfSrc,
                                     final JsonSerializationContext context) {
            String retVal;
            if (src == null) {
                retVal = "";
            } else {
                retVal = TIME_FORMAT.print(src);
            }
            return new JsonPrimitive(retVal);
        }
    
    }
    

    总结

    这两种方法都能实现对象的系列化和返系列化。方法一是采用流转换的,效率会高一些,但方法一是针对某一对象的,需要把这个对象的所以属性都要写一遍,如果这个对象有很多属性那就会多做很多体力劳动,而且只能是当前对象能用,不同对象还要重写一遍。而方法二就不同了,可以针对某一对象的某一个属性,具有通用性。

    参考文章

    Gson全解析(上)-Gson基础
    Gson全解析(中)-TypeAdapter的使用
    Gson全解析(下)-Gson性能分析

    相关文章

      网友评论

          本文标题:DateTime系列化与返系列化,Json解析问题

          本文链接:https://www.haomeiwen.com/subject/oqajzqtx.html