要解决我讨论的类型不匹配问题in this thread,我创建了自定义Deserializers
并将其添加到ObjectMapper
。然而,随着这种情况,性能显着下降。
使用默认的反序列化器,我在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;
}
};
}
}
我正在使用它来添加到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;
}
}
编辑:添加了额外数据
我的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
答案 0 :(得分:2)
物体有多大?代码基本上构建了一个树模型(一种dom树),这将占用与原始文档一样多3x-5x的内存。所以我假设您的输入是一个巨大的JSON文档。
您绝对可以使用Streaming API编写更高效的版本。类似的东西:
JsonParser jp = mapper.getJsonFactory().createJsonParser(input);
JsonToken t = jp.nextToken();
if (t == JsonToken.START_OBJECT) {
return mapper.readValue(jp, classToBindTo);
}
return null;
也可以使用数据绑定(如JsonDeserializer
)来实现它,但它只是因为你想委托给“默认”反序列化器而变得有点复杂。
为此,您需要实现BeanDeserializerModifier
,并在调用“modifyDeserializer”时替换标准反序列化器:您自己的代码可以保留对原始反序列化器的引用并委托给它,而不是使用中间树模型。
答案 1 :(得分:0)
如果你没有与杰克森联系,你也可以试试Genson http://code.google.com/p/genson/。 在您的情况下,有两个主要优点:性能不会松动,应该更容易实现。如果属性事件不以大写字母开头,则使用@JsonProperty(“Event”)对其进行注释(对于以大写字母开头的其他属性,也是如此)。 使用以下代码,您应该完成:
Genson genson = new Genson.Builder()
.withDeserializerFactory(new EventDeserializerFactory()).create();
YourRootClass[] bean = genson.deserialize(json, YourRootClass[].class);
class EventDeserializerFactory implements Factory<Deserializer<Event>> {
public Deserializer<Event> create(Type type, Genson genson) {
return new EventDeserializer(genson.getBeanDescriptorFactory().provide(Event.class,
genson));
}
}
class EventDeserializer implements Deserializer<Event> {
private final Deserializer<Event> standardEventDeserializer;
public EventDeserializer(Deserializer<Event> standardEventDeserializer) {
this.standardEventDeserializer = standardEventDeserializer;
}
public Event deserialize(ObjectReader reader, Context ctx) throws TransformationException,
IOException {
if (ValueType.ARRAY == reader.getValueType()) {
reader.beginArray().endArray();
return null;
}
return standardEventDeserializer.deserialize(reader, ctx);
}
}