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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM