zoukankan      html  css  js  c++  java
  • Json在序列化注意问题

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

    问题重现

    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中,一般是这样操作的。

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

    默认的话,返回ResponseBody,对象会直接序列化成json。这个时候,我们可以看一下返回的json。

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

    显然,和我们预期想的不太一样,多了一个jsonstr字段。这个时候我在想,是不是springmvc的问题。结果仔细一想,springnvc之所以可以直接将对象序列化成json,其实是我们添加的配置文件在起作用,真正参与序列化工作的是jackson这个库。于是,我单独使用了jackson,结果返回的json字符串和之前是相同的,这下就可以肯定是,jackson这个库本身的设计问题了。

    深入探讨

    带着这份好奇,我把java中常用的json序列化的库都试了一下,看看是否都是这样。主流的库有jackson、fastjson和gson。

    经过测试发现,jackson和阿里的fastjson返回的json字符串都带有一个jsonstr字段,唯独google的gson返回了我们预期的结果——只序列化对象的field。

    于是我找了下这几个库的序列化原理:

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

    参考文献

  • 相关阅读:
    Call KernelIoControl in user space in WINCE6.0
    HOW TO:手工删除OCS在AD中的池和其他属性
    关于新版Windows Server 2003 Administration Tools Pack
    关于SQL2008更新一则
    微软发布3款SQL INJECTION攻击检测工具
    HyperV RTM!
    OCS 2007 聊天记录查看工具 OCSMessage
    CoreConfigurator 图形化的 Server Core 配置管理工具
    OC 2007 ADM 管理模板和Live Meeting 2007 ADM 管理模板发布
    Office Communications Server 2007 R2 即将发布
  • 原文地址:https://www.cnblogs.com/kexianting/p/11649392.html
Copyright © 2011-2022 走看看