zoukankan      html  css  js  c++  java
  • JSON 解析 (三)—— FastJSON与Jackson比较

    一、方便性与性能

    调用方便性而言:

    • FastJSON提供了大量静态方法,调用简洁方便
    • Jackson须实例化类,调用相对繁琐,可通过封装成JSON工具类简化调用

    性能而言:

    • FastJSON反序列化的性能略差,对于256k的json字符串,平均700ms
    • Jackson 的 data binding反序列化的性能稍好,对于256k的json字符串,平均600ms
    • 两者的序列化性能基本相同,对于256k的json字符串,平均140ms
    • 相对data binding方式(ObjectMapper.writeValueAsString()),Jackson的流输出方式(JsonGenerator.writeObject())性能稍好,平均130ms

    二、其他

    1、序列化与反序列化的实现细节

    对象在序列化时,通过反射,遍历getter方法(getXXX(),isXXX),从方法名中获取属性名(XXX),并调用getter方法获取属性值,组合在一起,从而完成序列化;在反序列化时,遍历属性名(XXX)并拼接成setter方法(setXXX), 通过反射,查询并调用setter方法,从而完成对象构建。 序列化与反序列化的实现,与具体字段无直接关联,示例如下:

    public class Product {
        private String name;
        private Double price;
        // private boolean sold;
    
        public boolean isSold() { 
            return true; 
        } 
    
        // name、price的getter、setter方法  
        ... 
    }    
    @Test
    public void testBoolPOJO() {
        
        Product product = new Product();
        product.setName("hello");
        product.setPrice(12.36);
        
        String json = JSON.toJSONString(product);
        System.out.println(json);
        // {"name":"hello","price":12.36,"sold":true}
    
        Product product2 = JSON.parseObject(json, Product.class);
        System.out.println(product2.getName() + " " + product2.getPrice());
        // hello 12.36
    }

    如上所示,sold字段不存在,但在序列化时,可依据getter方法,在结果中生成该字段;在反序列化时,依据setter方法,上例即便存在sold字段(去掉该字段注释),由于不存在该字段的setter方法,无法从json字符串中获取到该属性值。

    《阿里巴巴Java编程规约》指出,在POJO类中,对布尔类型的变量,都不要加 is 前缀,如:定义为基本数据类型 Boolean isDeleted 的属性,它的方法是 isDeleted()、setIsDeleted(),在反向解析的时候,反序列化工具“误以为”对应的属性名称是 deleted,尝试调用setDeleted(),由于方法不存在,获取不到属性,可能抛出异常(如Jackson)

    2、FastJSON与Jackson在反序列化时的细微差异

    a、在反序列化时,默认情况下,如果根据Json字符串中的属性,在实体类中找不到对应的setter方法,FastJSON会忽略该属性,而Jackson会报错

    测试Product实体如上

    @Test
    public void testBoolPOJO2() throws Exception {
        Product product = new Product();
        product.setName("hello");
        product.setPrice(12.36);
        
        ObjectMapper objectMapper = new ObjectMapper();
        // objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        String json = objectMapper.writeValueAsString(product);
        System.out.println(json);
    
        Product product2 = objectMapper.readValue(json, Product.class); // 报错
        System.out.println(product2.getName() + " " + product2.getPrice());
    }

    通过配置DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES为fasle,可忽略多出的属性

    spring mvc使用的MappingJackson2HttpMessageConverter,在设置ObjectMapper的DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES时,在spring 3中为true,在spring 4及之后为false,因此,请求的json实体可包含冗余字段。

    详细可参考:关于jackson的DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES

    b、反序列化时,若找不到属性setter方面,Jackson会进一步查找同名字段,FastJSON则直接忽略

    public class Product {
        private String name;
        private Double price;
        private boolean sold;
    
        public boolean isSold() { 
            return this.sold; 
        } 
    
        // name、price的getter、setter方法  
        ... 
    }    
    @Test
    public void testBoolPOJO3() throws Exception {
        String json = "{"name":"hello","price":12.36,"sold":true}";
        
        ObjectMapper objectMapper = new ObjectMapper();
        Product product1 = objectMapper.readValue(json, Product.class);
        System.out.println(product1.isSold()); // true
        
        Product product2 = JSON.parseObject(json, Product.class);
        System.out.println(product2.isSold()); // false
    }

    参考:

    为什么阿里巴巴禁止接口返回值用枚举?

    关于jackson的DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES

  • 相关阅读:
    #QCon#北京2011大会“更有效地做测试”专题Slides资料
    长草了,冒个泡
    很好的一个书单
    团购——以价格换体验
    rpm deb命令集合[转]
    一个自动copy文件到指定目录的小程序
    ubuntulinux下的精品软件大汇总
    解决星际译王不朗读单词问题
    数据结构实验三:二叉树及其应用
    数据结构实验六:内部排序技术
  • 原文地址:https://www.cnblogs.com/MattCheng/p/8633010.html
Copyright © 2011-2022 走看看