浅谈Java中JSON的序列化问题

在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方法也就有它存在的意义了。  

相关文章
相关标签/搜索