2009-08-24 15 views
10

निम्नलिखित जैक्सन/जावा कोड है कि JSON में वस्तुओं को धारावाहिक में क्रमानुसार करने जैक्सन ObjectMapper का उपयोग करना, मैं इस हो रही है:JSON, में उपवर्ग नाम नहीं सुपर क्लास

{"animal":{"x":"x"}} 

हालांकि, क्या मैं वास्तव में प्राप्त करना चाहते हैं यह है:

{"dog":{"x":"x"}} 

वहाँ कुछ मैं AnimalContainer लिए कर सकते हैं, ताकि मैं वस्तु के क्रम प्रकार ("कुत्ता", "बिल्ली") मिलता है, "जानवर") के बजाय है? (संपादित करें: मुझे पता है कि नक्शा का नाम गेटर- और सेटर-विधि नामों से आता है।) एकमात्र तरीका जिसे मैं ऐसा करने के बारे में सोच सकता हूं वह है AnimalContainer के भीतर प्रत्येक प्रकार के पशु की विशेषता है उन सभी के लिए सेटर्स और गेटर्स, और लागू करें कि एक समय में केवल एक ही मूल्यवान है। लेकिन यह पशु superclass होने के उद्देश्य को हरा देता है और बस गलत लगता है। और मेरे असली कोड में मेरे पास वास्तव में एक दर्जन उप-वर्ग हैं, न केवल "कुत्ते" और "बिल्ली"। क्या ऐसा करने का कोई बेहतर तरीका है (शायद किसी भी तरह एनोटेशन का उपयोग करना)? मुझे भी deserializing के लिए एक समाधान की जरूरत है।

public class Test 
{ 
    public static void main(String[] args) throws Exception 
    { 
     AnimalContainer animalContainer = new AnimalContainer(); 
     animalContainer.setAnimal(new Dog()); 

     StringWriter sw = new StringWriter(); // serialize 
     ObjectMapper mapper = new ObjectMapper(); 
     MappingJsonFactory jsonFactory = new MappingJsonFactory(); 
     JsonGenerator jsonGenerator = jsonFactory.createJsonGenerator(sw); 
     mapper.writeValue(jsonGenerator, animalContainer); 
     sw.close(); 
     System.out.println(sw.getBuffer().toString()); 
    } 
    public static class AnimalContainer 
    { 
     private Animal animal; 
     public Animal getAnimal() {return animal;} 
     public void setAnimal(Animal animal) {this.animal = animal;} 
    } 
    public abstract static class Animal 
    { 
     String x = "x"; 
     public String getX() {return x;} 
    } 
    public static class Dog extends Animal {} 
    public static class Cat extends Animal {} 
} 

उत्तर

9

this announement के अनुसार, जैक्सन 1.5 पूर्ण पॉलिमॉर्फिक प्रकार हैंडलिंग लागू करता है, और ट्रंक में अब कोड एकीकृत है।

इस काम करने के लिए दो सरल तरीके हैं: ObjectMapper फोन करके

  • कॉन्फ़िगर वस्तु नक्शाकार

    • महाप्रकार में @JsonTypeInfo टिप्पणी जोड़ें (पशु यहाँ), या।enableDefaultTyping() (लेकिन यदि ऐसा है, तो पशु को अमूर्त प्रकार होना चाहिए)
  • +1

    पशु होने की आवश्यकता के बिना 'ObjectMapper.enableDefaultTyping()' के साथ हल करने का कोई तरीका है? मैं जैक्सन 1.9 का उपयोग कर रहा हूं और मैंने कोशिश की है लेकिन अभी भी काम नहीं कर रहा है ..... –

    +0

    डिफ़ॉल्ट टाइपिंग विभिन्न प्रकार के मानदंडों का उपयोग कर सकती है, जवाडॉक्स देखें, जिसमें कस्टम परिभाषा शामिल है, इसे किस पर लागू करना चाहिए। – StaxMan

    0

    यह एकमात्र तरीका है जिसे मैं ऐसा करने के बारे में सोच सकता हूं, और यह बदसूरत है। क्या कोई बेहतर तरीका है?

    @JsonWriteNullProperties(false) 
        public static class AnimalContainer 
        { 
         private Animal animal; 
    
         public Animal getCat() 
         { 
         return animal instanceof Cat ? animal : null; 
         } 
         public void setCat(Cat cat) 
         { 
         this.animal = cat; 
         } 
         public Animal getDog() 
         { 
         return animal instanceof Dog ? animal : null; 
         } 
         public void setDog(Dog dog) 
         { 
         this.animal = dog; 
         } 
         public Animal getFish() 
         { 
         return animal instanceof Fish ? animal : null; 
         } 
         public void setFish(Fish fish) 
         { 
         this.animal = fish; 
         } 
        } 
    
    2

    यह शायद नहीं जवाब आप के लिए देख रहे हैं यानी नहीं बगल में है, लेकिन उचित "बहुरूपी अक्रमांकन" लागू करने के लिए योजना नहीं है (और इसके लिए क्रमबद्धता पर आवश्यक सहायता), जैक्सन संस्करण 1.4 या तो के लिए (एक, 1.3, लेकिन उसके बाद एक)।

    वर्तमान संस्करण के लिए, आपको कस्टम सीरियलाइजर्स/deserializers को लागू करना होगा: मैं शायद deserialization के लिए कारखाने विधि को परिभाषित करना होगा, और serializer के लिए गेटटर टाइप करें ('getAnimalType' परिभाषित करें या सार के रूप में सार आधार वर्ग में जो भी हो, उप- कक्षाएं - या यहां तक ​​कि बेस क्लास में भी लागू करें, उदाहरण वर्ग के आउटपुट क्लास नाम?)।

    वैसे भी, सिर्फ मामले में यह मायने रखती है, यहाँ समस्याओं wrt JSON के साथ उप-वर्गों की हैंडलिंग को लागू करने, और स्कीमा भाषा के बिना (के बाद से json वास्तव में व्यापक रूप से एक का इस्तेमाल किया है नहीं करता है) अंतर्निहित रहे हैं:

    • कैसे मेटाडेटा से डेटा (बीन प्रॉपर्टी वैल्यू) को अलग करने के लिए (केवल उचित उप-वर्ग बनाने के लिए आवश्यक जानकारी टाइप करें) - अलग रखा जाना चाहिए, लेकिन प्रारूप के रूप में JSON को परिभाषित करने का कोई तरीका नहीं है (नामकरण सम्मेलन का उपयोग कर सकता है)
    • उचित एनोटेशन कैसे जोड़ें ऐसे मेटाडेटा उत्पन्न करने और उपयोग करने के लिए; और भाषा विशिष्ट विशेषताओं के आधार पर (उदाहरण के लिए जावा क्लास नामों को टाई नहीं करना चाहिए)

    ये हल करने योग्य समस्याएं हैं, लेकिन हल करने में मामूली आसान नहीं है। :-)

    +0

    कम से कम यह एक पुष्टि है कि जैक्सन (अभी तक) में ऐसा करने का कोई तरीका नहीं है, कि मुझे कुछ याद नहीं है; इसे कठिन तरीके से किया जाना है। – seansand

    +0

    सही - मैं जैक्सन 1.2 या उससे पहले के साथ इसे आसान तरीका (कस्टम सीरिएलाइज़र/deserializer के बिना) करने के तरीके के बारे में नहीं सोच सकता। – StaxMan

    +0

    एफडब्ल्यूआईडब्ल्यू, जैक्सन संस्करण 1.5 में deserialization के लिए बहुरूपता के पूर्ण हैंडलिंग के लिए समर्थन होगा (1.4 अभी जारी किया गया था)। – StaxMan