Gson的使用与理解

当今社会下,前后端分离,不同系统的信息交互,消息队列的数据传递,微服务的不同服务之间的数据处理,越来越多地方用到了序列化。序列化作为不同系统不同服务之间的数据桥梁。那么方便快捷的序列化工具还是必要的。

相对应配置在springboot本身的消息队列,使用gson进行代码中转化,具有不同情境下使用不同配置的优势。

该需求的来源还是来资源我这边和C#开发的系统进行数据对接时,导致的一些小问题。

我大致描述下对面系统的开发形式。现阶段,大家都是使用实体类的形式将整个实体类进行统一序列化。对方系统采用的是实体类嵌套实体类,关键该实体类还是写在同一个class下面的,也就存在一个问题,相同类型的实体类,写在不同class下面后导致部分的字段会存在一定的差异,虽然对面尽量避免这个问题了,但是偶尔还是出来了。更为关键的是,他们的首字母存在一会大写,一会小写的情况。给出的文档让我😭。

那么我这边采用字符串接收的形式,接收到之后,我再通过通过Gson的形式进行数据实例化。

那么在使用Gson的时候需要GsonBuilder来创建通过其进行gson实例化的简单配置。

1   private final Gson gson = new GsonBuilder()//建造者模式设置不同的配置
2             .serializeNulls()//序列化为null对象
3             .disableHtmlEscaping()//防止对网址乱码 忽略对特殊字符的转换
4             .registerTypeAdapter(String.class, new StringConverter())//对为null的字段进行转换
5             .registerTypeAdapter(Date.class, new DeanDateConverter())//对为null的字段进行转换
6             .create();
Gson创建

小伙伴们可以看到,我的类型适配是存在两个的,一种是String类型,一种是Date类型。String类型大家都好理解,为什么要使用Date类型呢,因为对面大量使用了java中的DateTime时间格式,中间还夹杂着正常的时间格式。DateTime默认事件格式是中间存在T的。那么就给自动转化时间类型提高了难度。那么干脆点,我直接将定义为Date类型的对应数据拉出来,通过字符串解析进行控制,不同的类型走不同的转换。

这里逻辑比较简单,我就直接上源码了

import com.google.gson.*;
import org.apache.http.util.TextUtils;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;

public class GsonBinder {

    //定义并配置gson
    private final Gson gson = new GsonBuilder()//建造者模式设置不同的配置
            .serializeNulls()//序列化为null对象
//            .setDateFormat("yyyy-MM-dd HH:mm:ss") //设置日期的格式
            .disableHtmlEscaping()//防止对网址乱码 忽略对特殊字符的转换
            .registerTypeAdapter(String.class, new StringConverter())//对为null的字段进行转换
            .registerTypeAdapter(Date.class, new DeanDateConverter())//对为null的字段进行转换
            .create();


    /**
     * 对解析数据的形式进行转换
     *
     * @param obj 解析的对象
     * @return 转化结果为json字符串
     */
    public String toJsonStr(Object obj) {
        if (obj == null) {
            return "";
        }
        try {
            return gson.toJson(obj);
        } catch (Exception e) {
            return "";
        }
    }

    /**
     * 解析为一个具体的对象
     *
     * @param json 要解析的字符串
     * @param obj  要解析的对象
     * @param <T>  将json字符串解析成obj类型的对象
     * @return
     */
    public <T> T toObj(String json, Class<T> obj) {
        //如果为null直接返回为null
        if (obj == null || TextUtils.isEmpty(json)) {
            return null;
        }
        try {
            return gson.fromJson(json, obj);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

    }

    /**
     * @return 不区分类型 传什么解析什么
     */
    public <T> T toObj(String jsonStr, Type type) {
        return gson.fromJson(jsonStr, type);
    }

    /**
     * 将Json数组解析成相应的映射对象列表
     * 解决类型擦除的问题
     */
    public <T> List<T> toList(String jsonStr, Class<T> clz) {
        List<T> list = gson.fromJson(jsonStr, new type(clz));
        if (list == null) list = new ArrayList<>();
        return list;
    }

    public <T> Map<String, T> toMap(String jsonStr, Class<T> clz) {
        Map<String, T> map = gson.fromJson(jsonStr, new type(clz));
        if (map == null) map = new HashMap<>();
        return map;
    }

    private class type implements ParameterizedType {
        private Type type;

        private type(Type type) {
            this.type = type;
        }

        @Override
        public Type[] getActualTypeArguments() {
            return new Type[]{type};
        }

        @Override
        public Type getRawType() {
            return ArrayList.class;
        }

        @Override
        public Type getOwnerType() {
            return null;
        }
    }

}
Gson代码
 1 import com.google.gson.*;
 2 import com.seekingtrue.dean.unit.DeanUtils;
 3 import org.joda.time.DateTime;
 4 
 5 import java.lang.reflect.Type;
 6 import java.text.ParseException;
 7 import java.util.Date;
 8 
 9 public class DeanDateConverter  implements JsonSerializer<Date>, JsonDeserializer<Date> {
10 
11     @Override
12     public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
13         System.out.println("时间类型");
14         String deanTemp  = json.toString().replace("\"","");
15         Date needDate=null;
16         if (deanTemp.equals("null")){
17             return needDate;
18         }
19         if (deanTemp.indexOf("T")!=-1){
20             DateTime dateTime = new DateTime(deanTemp);
21             needDate = dateTime.toDate();
22         }else {
23             DeanUtils deanUtils = new DeanUtils();
24             String fommate = "yyyy-MM-dd HH:mm:ss";
25             fommate.substring(0,deanTemp.length());
26             try {
27                 deanUtils.changeStringToDate(deanTemp,fommate);
28             } catch (ParseException e) {
29                 return null;
30             }
31         }
32         return needDate;
33     }
34 
35     @Override
36     public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext context) {
37         if (src==null){
38             return null;
39         }
40         DateTime dateTime = new DateTime(src);
41         return new JsonPrimitive(dateTime.toString());
42     }
43 }
时间类型转换

那么同一个字段不同名称如何处理呢,那么还是使用gson本身的配置功能。  @SerializedName(value = "BingRenID",alternate = {"bingRenID"}),别名多了就多配置点。问题就不大了。

posted @ 2022-09-06 11:27  DeanXue  阅读(209)  评论(0)    收藏  举报