Gson和FastJson 數據轉換的坑

1 Gson

1.1 Gson介紹:

  • GSON是Google提供的用來在Java對象和JSON數據之間進行映射的Java類庫。可以將一個Json字符轉成一個Java對象,或者將一個Java轉化爲Json字符串。

1.2 遇到的問題:本人在工作時遇到過這類問題:將Json轉換爲Java對象會發現精度丟失的問題,具體案例如下:

    public static void transferJsonToMap() {
        String json = "{"birthday":"1996-03-18","date":"May 10, 2019 3:32:17 PM","name":"joebig7","weight":65.5,"id":1412102169,"age":24,"height":179.2}";

        //將Json轉換爲Map
        Map<String, Object> map = JsonUtil.fromJson(json, new TypeToken<Map<String, Object>>() {
        }.getType());
        System.out.println(map);
    }
  
   輸出結果如下:
   {birthday=1996-03-18, date=May 10, 2019 3:32:17 PM, name=joebig7, weight=65.5, id=1.412102169E9, age=24.0, height=179.2}

可以發現通過Gson進行轉換後Map中的int類型變爲了Double,然後Long類型變爲了科學計數法的。

1.3 解決方法

  • 1 重寫類型適配器:首先需要明確的是,Gson通過一個類ObjectTypeAdapter來進行類型的轉換,主要代碼如下:

ERdecn.png

可以看見,Gson對於數據類型沒有做具體的區分,統一轉換成了Long類型。可以通過自定義一個類型轉換器來解決這個問題,具體d代碼如下: 代碼重寫了對Number類型對的處理邏輯

 public final class GeneralTypeAdapter extends TypeAdapter<Object> {
    @Override
    public Object read(JsonReader in) throws IOException {
        JsonToken token = in.peek();
        switch (token) {
            case BEGIN_ARRAY:
                List<Object> list = new ArrayList<Object>();
                in.beginArray();
                while (in.hasNext()) {
                    list.add(read(in));
                }
                in.endArray();
                return list;

            case BEGIN_OBJECT:
                Map<String, Object> map = new LinkedTreeMap<String, Object>();
                in.beginObject();
                while (in.hasNext()) {
                    map.put(in.nextName(), read(in));
                }
                in.endObject();
                return map;

            case STRING:
                return in.nextString();

            case NUMBER:
                String var1 = in.nextString();
                if (var1.contains(".") || var1.contains("e") || var1.contains("E")) {
                    return Double.parseDouble(var1);
                }
                return Long.parseLong(var1);

            case BOOLEAN:
                return in.nextBoolean();

            case NULL:
                in.nextNull();
                return null;

            default:
                throw new IllegalStateException();
        }
    }

    @Override
    public void write(JsonWriter out, Object value) throws IOException {

    }

}
    public static <T> T fromJson(String json, Type T) {
        GsonBuilder gsonBuilder = new GsonBuilder();

        Gson gson = gsonBuilder.registerTypeAdapter(new TypeToken<Map<String, Object>>() {
        }.getType(), new GeneralTypeAdapter()).create();

        return gson.fromJson(json, T);
    }

在實際使用中,最好將json轉換到具體的Bean對象就不會存在類型的問題。

2 FastJson

2.1 FastJson介紹: 和Gson類型,Fastjson是一個Java語言編寫的JSON處理器。

  • 遇到的問題:通過FastJson將json轉換成JSONObject或者Map類型的時候,對於浮點類型會被默認轉換成BigDecimal類型

2.2 解決方式:

    // 1 可以通過全局設置,禁用BigDeccimal的方式來解決這個問題
     public static void getJsonObject(String str){
        JSON.DEFAULT_PARSER_FEATURE &= ~Feature.UseBigDecimal.getMask();
        Map map = JSON.parseObject(str, Map.class);
        System.out.println(map.toString());
    }
    
    
    // 2 可以通過局部設置,禁用BigDeccimal
    public static void getJsonObject(String str){
        int disableDecimalFeature = JSON.DEFAULT_PARSER_FEATURE & ~Feature.UseBigDecimal.getMask();
        Map map = JSON.parseObject(str, Map.class,disableDecimalFeature);
        System.out.println(map.toString());
    }

不過在實際項目中,最好是定義具體的bean來進行轉換就不會出現這類問題

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章