Aby rozwiązać problem z niedopasowaniem typu, omówiono in this thread Utworzono niestandardowe Deserializers
i dodano je do ObjectMapper
. Jednak wydajność znacznie się pogarsza.Proces deserializacji w systemie Jackson z niestandardowym deserializerem powoduje wiele wywołań GC i zajmuje dużo dłużej.
Przy domyślnym deserializatorze otrzymuję 1-2 wywołania funkcji usuwania śmieci w logcat
, natomiast w przypadku niestandardowego deserializera są wywoływane co najmniej 7-8 wywołań GC, a zatem czas przetwarzania również znacznie się zwiększa.
My Deserializator:
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;
}
};
}
}
i używam tego, aby dodać do Mapper
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;
}
}
EDIT: Dodano dodatkowe informacje
Moje JSON jest o znacznych rozmiarach, ale nie ogromny : Wkleiłem it here
Teraz do analizowania tego samego JSON, jeśli mogę użyć tego kodu:
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;
Wtedy mój logcat jest like this
Ale jeśli mogę użyć tego kodu na samym 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;
Wtedy mój logcat jest like this
Jeden dodatkowy komentarz: zrobić absolutnie pewien, że ponowne użycie 'ObjectMapper' - jest to obiekt o dużej gramaturze i nie powinny być tworzone raz na zamówienie. W przeciwnym razie może zdecydowanie spowodować dużą aktywność GC. Trudno o tym wiedzieć z samego kodu powyżej. – StaxMan
Faktycznie zauważyłem, że twój deserializator tworzy obiekt ObjectMapper: jest to bardzo kosztowne. Możesz tego uniknąć, używając 'JsonParser.getCodec() ', rzutując wynik na' ObjectMapper' (co jest bezpiecznym upcastem). To też powinno trochę pomóc. – StaxMan
Zmodyfikowałem swój kod i dodałem obiekt odwzorowujący obiekty do mojego singletonu, wydajność poprawiła się dla domyślnego deserializera, ale problem z niestandardowym deserializerem nadal istnieje. Zauważyłem również, że jeśli dodaję dwa deserializery do tego samego modułu, to domyślny deserializer zostanie wywołany nie jako niestandardowy. 'JsonParser.getCodec()' nie jest metodą statyczną, więc będę musiał utworzyć 'JsonParser' dla każdego żądania. Czy to nie będzie zbyt drogie? – vKashyap