爲了解決我討論的類型不匹配問題in this thread我創建了自定義Deserializers
並將它們添加到ObjectMapper
。然而,這種性能會顯着惡化。Jackson使用自定義解串器進行反序列化會導致很多GC調用並花費很多時間
使用默認解串器時,我在logcat
中獲得1-2個垃圾收集調用,而使用自定義解串器時,至少有7-8個GC調用,因此處理時間也顯着增加。
我解串器:
public class Deserializer<T> {
public JsonDeserializer<T> getDeserializer(final Class<T> cls) {
return new JsonDeserializer<T>(){
@Override
public T deserialize(JsonParser jp, DeserializationContext arg1) throws IOException, JsonProcessingException {
JsonNode node = jp.readValueAsTree();
if (node.isObject()) {
return new ObjectMapper().convertValue(node, cls);
}
return null;
}
};
}
}
,我使用這個添加到映射器
public class DeserializerAttachedMapper<T> {
public ObjectMapper getMapperAttachedWith(final Class<T> cls , JsonDeserializer<T> deserializer) {
ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule(deserializer.toString(), new Version(1, 0, 0, null, null, null));
module.addDeserializer(cls, deserializer);
mapper.registerModule(module);
return mapper;
}
}
編輯:增加了額外的數據
我的JSON是相當的規模,但不是很大的: 我已粘貼it here
現在解析相同的JSON,如果我使用此代碼:
String response = ConnectionManager.doGet(mAuthType, url, authToken);
FLog.d("location object response" + response);
// SimpleModule module = new SimpleModule("UserModule", new Version(1, 0, 0, null, null, null));
// JsonDeserializer<User> userDeserializer = new Deserializer<User>().getDeserializer(User.class);
// module.addDeserializer(User.class, userDeserializer);
ObjectMapper mapper = new ObjectMapper();
// mapper.registerModule(module);
JsonNode tree = mapper.readTree(response);
Integer code = Integer.parseInt(tree.get("code").asText().trim());
if(Constants.API_RESPONSE_SUCCESS_CODE == code) {
ExploreLocationObject locationObject = mapper.convertValue(tree.path("response").get("locationObject"), ExploreLocationObject.class);
FLog.d("locationObject" + locationObject);
FLog.d("locationObject events" + locationObject.getEvents().size());
return locationObject;
}
return null;
然後我logcat的是like this
但是,如果我用同樣的JSON這個代碼
String response = ConnectionManager.doGet(mAuthType, url, authToken);
FLog.d("location object response" + response);
SimpleModule module = new SimpleModule("UserModule", new Version(1, 0, 0, null, null, null));
JsonDeserializer<User> userDeserializer = new Deserializer<User>().getDeserializer(User.class);
module.addDeserializer(User.class, userDeserializer);
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(module);
JsonNode tree = mapper.readTree(response);
Integer code = Integer.parseInt(tree.get("code").asText().trim());
if(Constants.API_RESPONSE_SUCCESS_CODE == code) {
ExploreLocationObject locationObject = mapper.convertValue(tree.path("response").get("locationObject"), ExploreLocationObject.class);
FLog.d("locationObject" + locationObject);
FLog.d("locationObject events" + locationObject.getEvents().size());
return locationObject;
}
return null;
然後我logcat的是like this
一個意見:一定要確保重用'ObjectMapper' - 這是一個重量級的對象,每次請求不應該被創建一次。否則,它肯定會導致很多GC活動。很難從上面的代碼肯定知道。 – StaxMan
其實我注意到你的反序列化器創建了一個ObjectMapper:這非常昂貴。你可以通過使用JsonParser來避免這種情況。getCodec()',將結果轉換爲ObjectMapper(這是安全的upcast)。這應該也有點幫助。 – StaxMan
我修改了我的代碼並將對象映射器添加到了我的單例中,默認解序器的性能得到了改進,但自定義解串器的問題仍然存在。另外,我注意到如果我將兩個反序列化器添加到同一個模塊,那麼默認的反序列化器會被調用而不是自定義的。 'JsonParser.getCodec()'不是一個靜態方法,所以我將不得不爲每個請求創建'JsonParser'。這不會太貴嗎? – vKashyap