Java中的Json序列化,不容忽視的getter

在開發的過程當中,常常會碰到和本身預期不同的狀況。有的時候本身去研究一下仍是頗有趣的。這兩天在寫java web的時候,碰到了一個對象序列化的問題。java

問題重現

public class AjaxJson {
    private boolean success;
    private String msg;
    private Object obj;
    private Map<String, Object> attributes;
    
    //getter and setter

    public String getJsonStr() {
        JSONObject obj = new JSONObject();
        obj.put("success", this.isSuccess());
        obj.put("msg", this.getMsg());
        obj.put("obj", this.obj);
        obj.put("attributes", this.attributes);
        return obj.toJSONString();
    }
}

上面是一個接口類,咱們須要把這個類的對象序列化成json返回。那麼在springmvc中,通常是這樣操做的。web

@RequestMapping(params = "/get")
@ResponseBody
public AjaxJson del(HttpServletRequest request) {
    AjaxJson json = new AjaxJson();
    //省略業務操做
    return json;
}

默認的話,返回ResponseBody,對象會直接序列化成json。這個時候,咱們能夠看一下返回的json。spring

{
    "success": "true",
    "Msg":"1",
    "obj":{
        ...
    },
    "attributes": null,
    "jsonStr":"{"success": "true","Msg":"1","obj":{...},"attributes": null,}"
}

顯然,和咱們預期想的不太同樣,多了一個jsonstr字段。這個時候我在想,是否是springmvc的問題。結果仔細一想,springnvc之因此能夠直接將對象序列化成json,實際上是咱們添加的配置文件在起做用,真正參與序列化工做的是jackson這個庫。因而,我單獨使用了jackson,結果返回的json字符串和以前是相同的,這下就能夠確定是,jackson這個庫自己的設計問題了。json

深刻探討

帶着這份好奇,我把java中經常使用的json序列化的庫都試了一下,看看是否都是這樣。主流的庫有jackson、fastjson和gson。mvc

通過測試發現,jackson和阿里的fastjson返回的json字符串都帶有一個jsonstr字段,惟獨google的gson返回了咱們預期的結果——只序列化對象的field。app

因而我找了下這幾個庫的序列化原理:post

  • jackson和fastjson
    在序列化的時候,先利用反射找到對象類的全部get方法,接下來去get,而後小寫化,做爲json的每一個key值,而get方法的返回值做爲value。接下來再反射field,添加到json中。
  • gson
    沒有找到通俗的講法,不過感受應該就和getter方法無關吧。

因此,能夠看大咱們的AjaxJson類中存在這樣一個getJsonStr,所以,jsonStr就做爲key,序列化到json中了。學習

固然在jackson中,提供了相應的annotation,能夠把這類方法忽略掉。在方法前加上@JsonIgnore 便可。測試

我的理解

  • 遇到問題的時候,千萬不要忽略一些簡單的地方,例如getter和setter方法。用getXXX的地方,能夠用fetch等替代。
  • 有時咱們會在類中定義例如private int mAge的變量,而getter的方法是getAge()。顯然咱們但願在序列化的時候獲得的key爲age而非mAge,那麼反射getter方法也就有它存在的意義了。

參考文獻

相關文章
相關標籤/搜索