Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/328.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Jackson使用自定义反序列化器进行反序列化会导致大量GC调用,并且需要更长的时间_Java_Android_Json_Jackson - Fatal编程技术网

Java Jackson使用自定义反序列化器进行反序列化会导致大量GC调用,并且需要更长的时间

Java Jackson使用自定义反序列化器进行反序列化会导致大量GC调用,并且需要更长的时间,java,android,json,jackson,Java,Android,Json,Jackson,为了解决所讨论的类型不匹配问题,我创建了自定义的反序列化程序,并将它们添加到ObjectMapper。但是,这样做会使性能显著恶化 使用默认反序列化程序,我在logcat中得到1-2个垃圾收集调用,而使用自定义反序列化程序,至少有7-8个GC调用,因此处理时间也显著增加 我的反序列化程序: public class Deserializer<T> { public JsonDeserializer<T> getDeserializer(final Class<T&

为了解决所讨论的类型不匹配问题,我创建了自定义的
反序列化程序
,并将它们添加到
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;
     }
 };
}
} 
公共类反序列化器{
公共JsonDeserializer getDeserializer(最终类cls){
返回新的JsonDeserializer(){
@凌驾
公共T反序列化(JsonParser jp,反序列化上下文arg1)抛出IOException,JsonProcessingException{
JsonNode=jp.readValueAsTree();
if(node.isObject()){
返回新的ObjectMapper().convertValue(节点,cls);
}
返回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;
   }
}
公共类反序列化AttachedMapper{
公共对象映射程序GetMapperateTachedWith(最终类cls,JsonDeserializer反序列化程序){
ObjectMapper mapper=新的ObjectMapper();
SimpleModule=new SimpleModule(反序列化程序.toString(),新版本(1,0,0,null,null,null));
addDeserializer模块(cls,反序列化器);
映射器注册表模块(模块);
返回映射器;
}
}
编辑:添加了额外数据

我的JSON相当大,但不是很大: 我已经贴好了

现在,如果我使用以下代码来解析相同的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;    
String response=ConnectionManager.doGet(mAuthType、url、authToken);
FLog.d(“位置对象响应”+响应);
//SimpleModule=new SimpleModule(“UserModule”,新版本(1,0,0,null,null));
//JsonDeserializer userDeserializer=新的反序列化程序().getDeserializer(User.class);
//module.addDeserializer(User.class,userDeserializer);
ObjectMapper mapper=新的ObjectMapper();
//映射器注册表模块(模块);
JsonNode tree=mapper.readTree(响应);
整数代码=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(“定位对象”+定位对象);
FLog.d(“locationObject事件”+locationObject.getEvents().size());
返回定位对象;
}       
返回null;
那么我的日志是

但是如果我对相同的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;        
String response=ConnectionManager.doGet(mAuthType、url、authToken);
FLog.d(“位置对象响应”+响应);
SimpleModule=new SimpleModule(“UserModule”,新版本(1,0,0,null,null));
JsonDeserializer userDeserializer=新的反序列化程序().getDeserializer(User.class);
module.addDeserializer(User.class,userDeserializer);
ObjectMapper mapper=新的ObjectMapper();
映射器注册表模块(模块);
JsonNode tree=mapper.readTree(响应);
整数代码=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(“定位对象”+定位对象);
FLog.d(“locationObject事件”+locationObject.getEvents().size());
返回定位对象;
}       
返回null;

那么我的logcat是

这个物体有多大?代码基本上构建了一个树模型(类似于dom树),这将占用原始文档3-5倍的内存。所以我假设您的输入是一个巨大的JSON文档

您肯定可以使用流式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”时替换标准的反序列化器:您自己的代码可以保留对原始反序列化器的引用并委托给它,而不是使用中间树模型。

如果您与jackson无关,您也可以尝试Genson。 在您的情况下,有两个主要优势:您不会在性能上松懈,它应该更容易实现。如果属性事件不以大写字母开头,请使用@JsonProperty(“事件”)对其进行注释(对于以大写字母开头的其他属性也是如此)。 应使用以下代码完成以下操作:

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);
    }
}
Genson Genson=new Genson.Builder()
.withDeserializerFactory(新事件DeserializerFactory()).create();
YourRootClass[]bean=genson.deserialize(json,YourRootClass[].class);
类EventDeserializerFactory实现工厂{
创建公共反序列化程序(类型,Genson-Genson){
返回新的EventDeserializer(genson.getBeanDescriptorFactory()。提供(Event.class、,
根森);
}
}
类EventDeserializer实现反序列化器{
私有最终反序列化程序standardEventDeserializer;
公共事件反序列化程序(反序列化程序standardEventDeserializer){
this.standardEventDeserializer=standardEventDeserializer;
}
公共事件反序列化(ObjectReader,Context ctx)引发TransformationException,
IOException{
if(ValueType.ARRAY==reader.getValueType()){
reader.beginArray().endArray();
返回null;
}
返回standardEventDeserializer.deserialize(读卡器,ctx);
}
}

谢谢你的回答。一定会尝试一下的。但是,我将首先尝试使用插孔提高性能