在Java Web開發的過程當中,時常會遇到與本身預期不同的狀況。有的時候靜下心來本身去研究一番內在的緣由仍是頗有趣的。這兩天在寫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
深刻探討mvc
帶着這份好奇,我把java中經常使用的json序列化的庫都試了一下,看看是否都是這樣。主流的庫有jackson、fastjson和gson。app
通過測試發現,jackson和阿里的fastjson返回的json字符串都帶有一個jsonstr字段,惟獨google的gson返回了咱們預期的結果——只序列化對象的field。測試
因而我找了下這幾個庫的序列化原理:fetch
jackson和fastjsonthis
在序列化的時候,先利用反射找到對象類的全部get方法,接下來去get,而後小寫化,做爲json的每一個key值,而get方法的返回值做爲value。接下來再反射field,添加到json中。google
gson
沒有找到通俗的講法,不過感受應該就和getter方法無關吧。
因此,能夠看大咱們的AjaxJson類中存在這樣一個getJsonStr,所以,jsonStr就做爲key,序列化到json中了。
固然在jackson中,提供了相應的annotation,能夠把這類方法忽略掉。在方法前加上@JsonIgnore 便可。
對此問題的理解
遇到問題的時候,千萬不要忽略一些簡單的地方,例如getter和setter方法。用getXXX的地方,能夠用fetch等替代。
有時咱們會在類中定義例如private int mAge的變量,而getter的方法是getAge()。顯然咱們但願在序列化的時候獲得的key爲age而非mAge,那麼反射getter方法也就有它存在的意義了。