8

このスレッドで説明されている型の不一致の問題を解決するために、カスタムを作成Deserializersして に追加しましたObjectMapper。ただし、これによりパフォーマンスが大幅に低下します。

デフォルトのデシリアライザーでは 1 ~ 2 回のガベージ コレクション呼び出しが行われますlogcatが、カスタム デシリアライザーでは少なくとも 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はかなりのサイズですが、巨大ではありません:ここに貼り付けました

このコードを使用する場合、同じ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は次のようになります

しかし、同じ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は次のようになります

4

2 に答える 2

2

オブジェクトの大きさはどれくらいですか?コードは基本的にツリーモデル(一種のdomツリー)を構築します。これには、元のドキュメントの3倍から5倍のメモリが必要です。したがって、入力は巨大な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;

これをデータバインディング(as JsonDeserializer)で実装することも可能ですが、「デフォルト」のデシリアライザーに委任したいという理由だけで少し複雑になります。これを行うには、を実装しBeanDeserializerModifier、「modifyDeserializer」が呼び出されたときに標準のデシリアライザーを置き換える必要があります。中間ツリーモデルを使用する代わりに、独自のコードで元のデシリアライザーへの参照を保持して委任できます。

于 2012-11-01T15:52:46.980 に答える
0

ジャクソンに縛られていない場合は、Genson http://code.google.com/p/genson/を試すこともできます。あなたの場合、主な利点が 2 つあります。パフォーマンスが低下することはなく、実装が容易になるはずです。プロパティ イベントが大文字で始まらない場合は、 @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);
    }
}
于 2012-11-01T20:06:15.430 に答える