代码改变世界
[登录 · 注册]
  • 去fastjson笔记
  • fastjson近些年频频爆出安全漏洞,现在已经是互联网的过街老鼠了,建议早去早好,网上搜索了下,相对而言google出品的gson目前还没听说有重大安全问题。下面是gson替换fastjson可能会遇到的一些坑。

    一、美化输出格式

    new GsonBuilder().setPrettyPrinting().create();

    二、自定义date的输出格式

    new GsonBuilder()
        .setPrettyPrinting() //美化输出格式
        .setDateFormat("yyyy-MM-dd HH:mm:ss.SSS") //设置date字段的输出格式
        .create();
    

    写一段单元测试代码:

    package test.nio.study;
    
    import com.google.gson.Gson;
    import com.google.gson.GsonBuilder;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    import org.junit.Test;
    
    import java.util.*;
    
    public class GsonTest {
    
        public Gson gson() {
            return new GsonBuilder()
                    .setPrettyPrinting() //美化输出格式
                    .setDateFormat("yyyy-MM-dd HH:mm:ss.SSS") //设置date字段的输出格式
                    .create();
        }
    
        @Data
        @NoArgsConstructor
        public class InnerTestClass {
            private Integer intField;
            private Long longField;
            private String strField;
            private Date dateField;
            private List<InnerTestClass> listField;
            private Map<String, String> mapField;
        }
    
        @Test
        public void testGson() {
            InnerTestClass test = new InnerTestClass();
            test.intField = 1;
            test.longField = 2L;
            test.dateField = new Date();
            test.mapField = new HashMap<>();
            test.mapField.put("test", "hello world");
            test.listField = new ArrayList<>();
    
            InnerTestClass test2 = new InnerTestClass();
            test2.dateField = new Date();
            test.listField.add(test2);
    
            System.out.println(gson().toJson(test));
        }
    }
    

    输出如下:

    {
      "intField": 1,
      "longField": 2,
      "dateField": "2020-06-14 23:04:17.202",
      "listField": [
        {
          "dateField": "2020-06-14 23:04:17.202"
        }
      ],
      "mapField": {
        "test": "hello world"
      }
    }
    

      

    三、兼容多种date字符串/timestamp的反序列化

    {
        "dateField": "2020-06-14 23:04:17",
        "listField": [
            {
                "dateField": "2020-06-14 23:04:17.202"
            },
            {
                "dateField": 1592148201102
            },
            {
                "dateField": ""
            }
        ]
    }
    

    如果上面这段json,尝试用刚才生成的gson实例反序列化的话,会报错Invalid time zone indicator ' ',原因是 第1个dateField没有带.SSS的毫秒部分,第3个dateField是一个timestamp的long型数字,更无法匹配yyyy-MM-dd HH:mm:ss.SSS,第4个是空字符串,仍然无法匹配。

    可以参考下面这样:

    public Gson gson() {
        String dateFormatWithMS = "yyyy-MM-dd HH:mm:ss.SSS";
        String dateFormatNoMS = "yyyy-MM-dd HH:mm:ss";
        GsonBuilder builder = new GsonBuilder();
        builder.registerTypeAdapter(Date.class, (JsonDeserializer<Date>) (json, typeOfT, context) -> {
            if (json == null || json.toString().equalsIgnoreCase("""")) {
                //空字符判断
                return null;
            }
            JsonPrimitive jsonPrimitive = json.getAsJsonPrimitive();
            SimpleDateFormat sdfMS = new SimpleDateFormat(dateFormatWithMS);
            SimpleDateFormat sdfNoMS = new SimpleDateFormat(dateFormatNoMS);
            Date dt = null;
            try {
                if (jsonPrimitive.isString()) {
                    if (jsonPrimitive.getAsString().length() == 19) {
                        //这里只是示例,简单用长度来判断是哪种格式
                        //yyyy-MM-dd HH:mm:ss格式
                        dt = sdfNoMS.parse(json.getAsString());
                    } else {
                        //yyyy-MM-dd HH:mm:ss.SSS格式
                        dt = sdfMS.parse(json.getAsString());
                    }
                } else if (jsonPrimitive.isNumber()) { //兼容timestamp类型
                    dt = new Date(jsonPrimitive.getAsLong());
                }
            } catch (Exception e) {
                //错误日志记录,略
                e.printStackTrace();
            }
            return dt;
        });
        Gson gson = builder
                .setDateFormat(dateFormatWithMS)
                .setPrettyPrinting()
                .create();
        return gson;
    }
    

    这样,刚才这4种情况的date解析都能兼容了。

    四、字段别名

    @SerializedName(value = "int_field", alternate = {"aaa", "bbb"})
    private Integer intField;    
    

    这样的话,json字符串中的int_field, aaa, bbb这3种名字,都能映射到intField上。 

    五、数组解析

        @Test
        public void testParseList() {
            String json = "["A","B","C"]";
            List<String> list1 = gson().fromJson(json, new TypeToken<List<String>>() {
            }.getType());
            System.out.println(list1.size());
        }
    

    TypeToken是个很有用的东西,建议大家多研究

  • 上一篇:java:线上问题排查常用手段
    下一篇:如何让java中的注释代码执行?
  • 【推广】 阿里云小站-上云优惠聚集地(新老客户同享)更有每天限时秒杀!
    【推广】 云服务器低至0.95折 1核2G ECS云服务器8.1元/月
    【推广】 阿里云老用户升级四重礼遇享6.5折限时折扣!
  • 原文:https://www.cnblogs.com/yjmyzz/p/replace-fastjson-with-gson.html
走看看 - 开发者的网上家园