2012-11-01 16 views
7

मेरी टाइप मिस्चैच समस्या को हल करने के लिए in this thread पर चर्चा की गई मैंने कस्टम Deserializers बनाया और उन्हें ObjectMapper पर जोड़ा। हालांकि प्रदर्शन इसके साथ काफी खराब हो जाता है।कस्टम deserializer के साथ जैक्सन deserializing बहुत सारे जीसी कॉल का कारण बनता है और बहुत अधिक समय लेता है

डिफ़ॉल्ट deserializer के साथ मुझे logcat में 1-2 कचरा संग्रहण कॉल मिलती है जबकि कस्टम deserializer के साथ कम से कम 7-8 जीसी कॉल हैं, और इसलिए प्रसंस्करण समय भी काफी बढ़ता है।

मेरे deserializer:

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

+0

एक अतिरिक्त टिप्पणी: पूरी तरह से सुनिश्चित आप पुन: उपयोग कर 'ObjectMapper' - यह एक भारी वजन वस्तु है और अनुरोध के अनुसार एक बार नहीं बनाया जाना चाहिए। अन्यथा यह निश्चित रूप से बहुत सी जीसी गतिविधि का कारण बन सकता है। उपर्युक्त कोड से निश्चित रूप से जानना मुश्किल है। – StaxMan

+0

असल में मैंने देखा कि आपका deserializer एक ऑब्जेक्टमैपर बनाता है: यह बहुत महंगा है। आप 'जेसन पार्सर' का उपयोग करके इससे बच सकते हैं।getCodec() ', कास्टिंग परिणाम 'ऑब्जेक्टमैपर' (जो सुरक्षित अपस्टास्ट है)। इससे काफी मदद मिलनी चाहिए। – StaxMan

+0

मैंने अपने कोड को संशोधित किया और ऑब्जेक्ट मैपर को मेरे सिंगलटन में जोड़ा, प्रदर्शन डिफ़ॉल्ट डिसेराइज़र के लिए बेहतर हुआ लेकिन कस्टम deserializer के साथ समस्या अभी भी वहाँ है। साथ ही, मैंने देखा कि यदि मैं एक ही मॉड्यूल में दो deserializers जोड़ता हूं तो डिफ़ॉल्ट deserializer कस्टम एक नहीं कहा जाता है। 'JsonParser.getCodec() 'एक स्थिर विधि नहीं है, इसलिए मुझे प्रत्येक अनुरोध के लिए' JsonParser' बनाना होगा। क्या वह महंगा भी नहीं होगा ?? – vKashyap

उत्तर

2

वस्तु कितनी बड़ी है? कोड मूल रूप से एक पेड़ मॉडल (डोम पेड़ का प्रकार) बनाता है, और यह मूल दस्तावेज़ के रूप में 3x-5x जितनी मेमोरी की तरह कुछ ले जाएगा। तो मुझे लगता है कि आपका इनपुट एक विशाल JSON दस्तावेज़ है।

आप निश्चित रूप से स्ट्रीमिंग एपीआई का उपयोग करके एक और अधिक कुशल संस्करण लिख सकते हैं। कुछ की तरह:

JsonParser jp = mapper.getJsonFactory().createJsonParser(input); 
JsonToken t = jp.nextToken(); 
if (t == JsonToken.START_OBJECT) { 
    return mapper.readValue(jp, classToBindTo); 
} 
return null; 

यह भी संभव है (JsonDeserializer के रूप में) डेटा-बाइंडिंग के साथ इस लागू करने के लिए, लेकिन यह जटिल सा सिर्फ इसलिए कि आप "डिफ़ॉल्ट" deserializer को सौंपना चाहते हैं हो जाता है। ऐसा करने के लिए, आपको BeanDeserializerModifier को कार्यान्वित करने की आवश्यकता होगी, और जब "संशोधित डीसेरियलाइज़र" कहा जाता है तो मानक deserializer को प्रतिस्थापित करें: आपका स्वयं का कोड मूल deserializer के संदर्भ को बनाए रख सकता है और मध्यवर्ती पेड़ मॉडल का उपयोग करने के बजाय इसे प्रतिनिधि बना सकता है।

+0

मैंने अपना प्रश्न संपादित किया है और JSON, पार्सिंग कोड और लॉग जोड़े हैं। धन्यवाद – vKashyap

0

यदि आप जैक्सन से बंधे नहीं हैं तो आप जेन्सन http://code.google.com/p/genson/ भी कोशिश कर सकते हैं। आपके मामले में दो मुख्य फायदे हैं: आप प्रदर्शन में ढीले नहीं होंगे, इसे कार्यान्वित करना आसान होना चाहिए। यदि संपत्ति घटना ऊपरी अक्षर से शुरू नहीं होती है तो इसे @ जेसनप्रोपर्टी ("ईवेंट") के साथ एनोटेट करें (ऊपरी अक्षर से शुरू होने वाली अन्य गुणों के लिए)। निम्नलिखित कोड आप से किया जाना चाहिए साथ:

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); 
    } 
} 
+0

उत्तर के लिए धन्यवाद। निश्चित रूप से इसे एक शॉट दे देंगे। लेकिन, एटीएम मैं पहले जैक्सन के साथ प्रदर्शन में सुधार करने की कोशिश करूंगा। – vKashyap