一、方便性與性能
調用方便性而言:
- 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
