2015-06-03 8 views
10

नीचे दिया गया उदाहरण एक वर्ग (क्लब) दिखाता है जिसमें एक अमूर्त वर्ग (सदस्य) का संग्रह होता है। मैं इस बात से भ्रमित हूं कि मुझे Deserialization सही तरीके से काम करने के लिए टाइपएडाप्टर या जेसनडेसरियलज़र की आवश्यकता है या नहीं। सीरियलाइजेशन किसी भी मदद के बिना ठीक काम करता है, लेकिन Deserialization अपवाद फेंक रहा है। उदाहरण के लिए मैंने निम्नलिखित "क्लोन" परीक्षण बनाया है। यदि कोई कामकाजी उदाहरण दिखा सकता है तो मैं बहुत आभारी रहूंगा।जीसन प्रकार एडाप्टर बनाम कस्टम Deseralizer

पहले क्लब क्लास

package gson.test; 
import java.util.ArrayList; 

import com.google.gson.Gson; 

public class Club { 
    public static void main(String[] args) { 
     // Setup a Club with 2 members 
     Club myClub = new Club(); 
     myClub.addMember(new Silver()); 
     myClub.addMember(new Gold()); 

     // Serialize to JSON 
     Gson gson = new Gson(); 
     String myJsonClub = gson.toJson(myClub); 
     System.out.println(myJsonClub); 

     // De-Serialize to Club 
     Club myNewClub = gson.fromJson(myJsonClub, Club.class); 
     System.out.println(myClub.equals(myNewClub) ? "Cloned!" : "Failed"); 
    } 

    private String title = "MyClub"; 
    private ArrayList<Member> members = new ArrayList<Member>(); 

    public boolean equals(Club that) { 
     if (!this.title.equals(that.title)) return false; 
     for (int i=0; i<this.members.size(); i++) { 
      if (! this.getMember(i).equals(that.getMember(i))) return false; 
     } 
     return true; 
    } 
    public void addMember(Member newMember) { members.add(newMember); } 
    public Member getMember(int i) { return members.get(i); } 
} 

अब सार बेस कक्षा सदस्य

package gson.test; 
public abstract class Member { 
    private int type; 
    private String name = ""; 

    public int getType() { return type; } 
    public void setType(int type) { this.type = type; } 
    public boolean equals(Member that) {return this.name.equals(that.name);} 
} 

और (स्वर्ण और रजत) सदस्य के दो ठोस उप-वर्गों

package gson.test; 
public class Gold extends Member { 
    private String goldData = "SomeGoldData"; 
    public Gold() { 
     super(); 
     this.setType(2); 
    } 
    public boolean equals(Gold that) { 
     return (super.equals(that) && this.goldData.equals(that.goldData)); 
    } 
} 

package gson.test; 
public class Silver extends Member { 
    private String silverData = "SomeSilverData"; 
    public Silver() { 
     super(); 
     this.setType(1); 
    } 
    public boolean equals(Silver that) { 
     return (super.equals(that) && this.silverData.equals(that.silverData)); 
    } 
} 

और अंत में आउटपुट

{"title":"MyClub","members":[{"silverData":"SomeSilverData","type":1,"name":""},{"goldData":"SomeGoldData","type":2,"name":""}]} 
    Exception in thread "main" java.lang.RuntimeException: Failed to invoke public gson.test.Member() with no args 
     at com.google.gson.internal.ConstructorConstructor$3.construct(ConstructorConstructor.java:107) 
     at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:186) 
... 
+1

बराबर() विधि को 'ऑब्जेक्ट' पैरामीटर प्रकार लेना चाहिए, न कि 'क्लब' –

+0

धन्यवाद, यह मुझे पकड़ने के लिए थोड़ा सा ले जाएगा। –

+0

समझ गया, धन्यवाद, मैं अगली बार अप-वोट करूंगा। –

उत्तर

13

आप दोनों कर सकते हैं। आप जो भी चुनते हैं वह वास्तव में संभावित प्रदर्शन प्रभाव पर निर्भर करता है, और कितना कोड लिखने को तैयार है।

Deserializers अधिक महंगा हैं। इसका कारण यह है कि deserializer में इनपुट एक जेसन पेड़ है, और जीएसओएन को आपकी कक्षा से मेल खाने वाली संपत्ति के पूर्ण जेसन एलिमेंट सबट्री को बनाना होगा, इससे पहले कि यह आपके deserializer को पास कर सके। यदि आपके वर्गों में बहुत घोंसले हैं, तो लागत बढ़ जाती है। सादे वस्तुओं के लिए, यह नगण्य होगा।

ऐसा लगता है कि आपको पता चलेगा कि कौन सी कक्षा type संपत्ति के मूल्य के आधार पर बनाई जाएगी जो लक्ष्य वस्तु में शामिल की जाएगी। आपका deserializer, प्रकार

  • कॉल context.deserialize() वर्ग और एक ही तत्व है कि आप करने के लिए पारित किया गया था के साथ पारित JsonElement वस्तु में करने के लिए

    • देखो की आवश्यकता होगी type संपत्ति पढ़ते हैं, यह निर्धारित
    • अगर एक त्रुटि फेंक प्रकार गुम या अवैध था

    आपके प्रकार एडाप्टर को और अधिक जटिल होना होगा। प्रकार एडाप्टर में इनपुट धारा है, तत्व/subtree नहीं। आप पूरी तरह से स्ट्रीम से अगले मान को लोड कर सकते हैं, इसे पार्स कर सकते हैं, और फिर वही कर सकते हैं जो deserializer किया था, जो समझ में नहीं आता है और आप बस deserializer इंटरफ़ेस का उपयोग कर सकते हैं। वैकल्पिक रूप से, आप स्ट्रीम को पढ़ सकते हैं, देख सकते हैं कि कौन से गुण हैं, उन्हें स्थानीय चरों में सहेजें, जब तक कि आप type संपत्ति (आप इसके स्थान की भविष्यवाणी नहीं कर सकते) तक पहुंच जाएं, फिर शेष गुणों को पढ़ना समाप्त करें, और अपना अंतिम बनाएं Gold/Silver वस्तुओं के आधार पर वस्तुओं, और सभी गुणों को पढ़ और सहेजा गया।

  • +0

    मैं परीक्षण के माध्यम से पहुंचा, मेरा सीरियलाइजेशन काम नहीं कर रहा है जैसा मैंने सोचा था, ऐसा लगता है कि मुझे संग्रह के उपप्रकारों में गोता लगाने के लिए एक विशेष धारावाहिक की भी आवश्यकता है। जब मैं एक होता हूं तो मैं अंतिम कामकाजी उदाहरण का परीक्षण और पोस्ट करना जारी रखूंगा। –

    8

    ठीक है, असली कामकाजी उदाहरण (मुझे इस बार निश्चित रूप से यकीन है)।

    क्लब

    package gson.test; 
    import java.util.ArrayList; 
    import com.google.gson.Gson; 
    import com.google.gson.GsonBuilder; 
    
    public class Club { 
        public static void main(String[] args) { 
         // Setup a Club with 2 members 
         Club myClub = new Club(); 
         myClub.addMember(new Silver("Jack")); 
         myClub.addMember(new Gold("Jill")); 
         myClub.addMember(new Silver("Mike")); 
    
         // Get the GSON Object and register Type Adapter 
         GsonBuilder builder = new GsonBuilder(); 
         builder.registerTypeAdapter(Member.class, new MemberDeserializer()); 
         builder.registerTypeAdapter(Member.class, new MemberSerializer()); 
         builder.setPrettyPrinting(); 
         Gson gson = builder.create(); 
    
         // Serialize Club to JSON 
         String myJsonClub = gson.toJson(myClub); 
    
         // De-Serialize to Club 
         Club myNewClub = gson.fromJson(myJsonClub, Club.class); 
         System.out.println(myClub.equals(myNewClub) ? "Cloned!" : "Failed"); 
         System.out.println(gson.toJson(myNewClub)); 
        } 
    
        private String title = "MyClub"; 
        private ArrayList<Member> members = new ArrayList<Member>(); 
    
        public boolean equals(Object club) { 
         Club that = (Club) club; 
         if (!this.title.equals(that.title)) return false; 
         for (int i=0; i<this.members.size(); i++) { 
          Member member1 = this.getMember(i); 
          Member member2 = that.getMember(i); 
          if (! member1.equals(member2)) return false; 
         } 
         return true; 
        } 
        public void addMember(Member newMember) { members.add(newMember); } 
        public Member getMember(int i) { return members.get(i); } 
    } 
    

    सदस्य सार कक्षा

    package gson.test; 
    public abstract class Member { 
        private String clsname = this.getClass().getName() ; 
        private int type; 
        private String name = "unknown"; 
    
        public Member() { } 
        public Member(String theName) {this.name = theName;} 
        public int getType() { return type; } 
        public void setType(int type) { this.type = type; } 
        public boolean equals(Object member) { 
         Member that = (Member) member; 
         return this.name.equals(that.name); 
        } 
    } 
    

    कंक्रीट उप-वर्ग सिल्वर और गोल्ड

    package gson.test; 
    public class Silver extends Member { 
        private String silverData = "SomeSilverData"; 
        public Silver() { 
         super(); 
         this.setType(1); 
        } 
        public Silver(String theName) { 
         super(theName); 
         this.setType(1); 
        } 
        public boolean equals(Object that) { 
         Silver silver = (Silver)that; 
         return (super.equals(that) && this.silverData.equals(silver.silverData)); 
        } 
    } 
    
    package gson.test; 
    public class Gold extends Member { 
        private String goldData = "SomeGoldData"; 
        private String extraData = "Extra Gold Data"; 
        public Gold() { 
         super(); 
         this.setType(2); 
        } 
        public Gold(String theName) { 
         super(theName); 
         this.setType(2); 
        } 
        public boolean equals(Gold that) { 
         Gold gold = (Gold) that; 
         return (super.equals(that) && this.goldData.equals(gold.goldData)); 
        } 
    } 
    

    कस्टम सदस्य Serailizer

    package gson.test; 
    import java.lang.reflect.Type; 
    import com.google.gson.JsonElement; 
    import com.google.gson.JsonSerializationContext; 
    import com.google.gson.JsonSerializer; 
    
    public class MemberSerializer implements JsonSerializer<Member> { 
    
        public JsonElement serialize(Member src, Type member, JsonSerializationContext context) { 
         switch (src.getType()) { 
          case 1: return context.serialize((Silver)src); 
          case 2: return context.serialize((Gold)src); 
          default: return null; 
         } 
        } 
    } 
    

    कस्टम deserializer

    package gson.test; 
    import java.lang.reflect.Type; 
    import com.google.gson.JsonDeserializationContext; 
    import com.google.gson.JsonDeserializer; 
    import com.google.gson.JsonElement; 
    
    public class MemberDeserializer implements JsonDeserializer<Member> { 
        @Override 
        public Member deserialize(JsonElement json, Type member, JsonDeserializationContext context) { 
         int myType = json.getAsJsonObject().get("type").getAsInt(); 
         switch (myType) { 
          case 1: return context.deserialize(json, Silver.class); 
          case 2: return context.deserialize(json, Gold.class); 
          default: return null; 
         } 
        } 
    } 
    

    और ... उत्पादन

    Cloned! 
    { 
        "title": "MyClub", 
        "members": [ 
        { 
         "silverData": "SomeSilverData", 
         "clsname": "gson.test.Silver", 
         "type": 1, 
         "name": "Jack" 
        }, 
        { 
         "goldData": "SomeGoldData", 
         "extraData": "Extra Gold Data", 
         "clsname": "gson.test.Gold", 
         "type": 2, 
         "name": "Jill" 
        }, 
        { 
         "silverData": "SomeSilverData", 
         "clsname": "gson.test.Silver", 
         "type": 1, 
         "name": "Mike" 
        } 
        ] 
    } 
    

    मैं नोट करना चाहिए मेरा असली यूज-केस एक जहां प्रदर्शन एक मुद्दा नहीं होना चाहिए, मैं एक लोड हो रहा है कर रहा हूँ यह है कि जेएसओएन टेक्स्ट फाइलों से ऑब्जेक्ट्स का कैश ताकि इस कोड के साथ आवृत्ति निष्पादित की जा सके, प्रदर्शन को बनाए रखने से काफी कम महत्वपूर्ण बनाता है।

    संबंधित मुद्दे