2013-04-17 11 views
8

में XML में वहाँ एक कनवर्टर या कुछ आपरेशन कि हर एक रूपांतरण के बाद किया जाता है बनाने के लिए एक तरीका है? संदर्भ के लिए, यदि मैं अपना डेटा मॉडल बदलता हूं तो पिछली संगतता को बनाए रखने के लिए मैं अपने एक्सएमएल में मौजूद फ़ील्ड के लिए डिफ़ॉल्ट मानों को पॉप्युलेट करने की कोशिश कर रहा हूं। उदाहरण के लिए, अगर मैं इस वस्तु था:सेट डिफ़ॉल्ट मान नहीं Xstream

class A { 
    private String b; 
    private String c; 
    private String d; 
} 

और मेरे एक्सएमएल था कुछ की तरह:

<a> 
<b>b</b> 
<d>d</d> 
</a> 

मैं एक्सएमएल के अपने आयात चाहते हैं पता करने के लिए क्षेत्र c लिए एक डिफ़ॉल्ट मान है कि वहाँ कि "c" है और A जैसे पर यह निर्धारित किया है। यह एक सामान्य ऑपरेशन होना चाहिए जिसमें मैं एक जटिल ग्राफ के किसी भी क्षेत्र में डिफ़ॉल्ट जोड़ सकता हूं। अगर वहाँ किसी तरह हर रूपांतरण के बाद एक समारोह को ट्रिगर किए, यह वस्तुओं मैं पर एक डिफ़ॉल्ट मान सेट करना चाहते हैं का एक नक्शा के खिलाफ मौजूदा वस्तु की जांच कर सकता है।

यह भी ध्यान दें कि readResolve/readObject का उपयोग 1 से एक विकल्प प्रतीत नहीं होता है। ReadObject() कभी भी मेरे लिए काम नहीं कर रहा था और 2. readResolve फ़ील्ड को डिफ़ॉल्ट मान के साथ ओवरराइट कर देगा, भले ही यह वास्तव में था एक्सएमएल में शामिल अगर मेरी धारणाएं यहां गलत हैं तो कृपया मुझे बताएं।

संपादित :: मैं उपयोगकर्ता मेलिंग सूची पर इस संबंधित धागा मिला: http://article.gmane.org/gmane.comp.java.xstream.user/4619/match=default+value

और ऐसा लगता ही सुझाव दिया समाधान की तरह readResolve() जो मैं पहले से ही कहा एक मान्य समाधान नहीं था उपयोग करने के लिए है।

उत्तर

1

आप एक कनवर्टर की आवश्यकता होगी।

यहाँ अपने मामले के लिए एक कोड उदाहरण है:

public class AConverter implements Converter { 

    @Override 
public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { 
    A a = new A(); 
    String bValue = "b"; 
    String cValue = "c"; 
    String dValue = "d"; 

    while (reader.hasMoreChildren()) { 
     reader.moveDown(); 
     if ("b".equals(reader.getNodeName())) { 
      bValue = reader.getValue(); 
     } else if ("c".equals(reader.getNodeName())) { 
      cValue = reader.getValue(); 
     } else if ("d".equals(reader.getNodeName())) { 
      dValue = reader.getValue(); 
     } 
     reader.moveUp(); 
    } 
    a.setB(bValue); 
    a.setC(cValue); 
    a.setD(dValue); 

    return a; 
} 

@Override 
public void marshal(Object object, HierarchicalStreamWriter writer, MarshallingContext context) { 
    A a = (A) object; 
    writer.startNode("b"); 
    writer.setValue(a.getB()); 
    writer.endNode(); 
    writer.startNode("c"); 
    writer.setValue(a.getC()); 
    writer.endNode(); 
    writer.startNode("d"); 
    writer.setValue(a.getD()); 
    writer.endNode(); 


} 

@Override 
public boolean canConvert(Class clazz) { 
    return clazz == A.class; 
} 

}

मत भूलना कनवर्टर रजिस्टर करने के लिए:

XStream xs = new XStream(); 
xs.registerConverter(new AConverter()); 

संपादित करें: कनवर्टर कोड फिक्स्ड।

+0

धन्यवाद पाब्लोसारीवा, लेकिन यह केवल कुछ कक्षा ए के लिए स्पष्ट रूप से काम करेगा। मुझे अपने पूर्ण ऑब्जेक्ट ग्राफ़ में किसी ऑब्जेक्ट में सामान्य रूप से काम करने की आवश्यकता है। इसलिए इसे ऑब्जेक्ट्स बी/सी/डी, और किसी भी ऑब्जेक्ट्स के लिए काम करना है जो बी सी डी के पास भी हो सकता है। इसके अलावा, अगर इस मामले में अतिरिक्त फ़ील्ड जोड़े गए थे, तो इसे इस कनवर्टर को बनाए रखने की आवश्यकता होगी। आदर्श रूप से, मैं बस कुछ नया डीफॉल्टफिल्ल्ड (क्लासविथन्यूडफॉल्ट.क्लास, न्यूफिल्ल्डनाम, न्यूडिफॉल्ट वैल्यू) जैसा कुछ कह सकता हूं, मुझे किसी भी समय एक नया डिफ़ॉल्ट जोड़ने की आवश्यकता है। – eipark

+0

खिलौना की समस्या के लिए यह केवल खिलौना समाधान है। आपको डिफ़ॉल्ट मान वाले प्रत्येक वर्ग में कनवर्टर की आवश्यकता होगी। आपको अनमशाल में हाथों से वस्तुओं को बनाने की जरूरत नहीं है, आप इसकी देखभाल करने के लिए एक कारखाना रख सकते हैं। मुझे उम्मीद है यह मदद करेगा। – pablosaraiva

+0

दाएं। मुझे लगता है कि लक्ष्य किसी वास्तविक रखरखाव से बचने के लिए है जो जटिल और हाथ से जल्दी हो सकता है। दुर्भाग्यवश मुझे नहीं लगता कि एक्सस्ट्रीम प्रत्येक के लिए कन्वर्टर्स से परे, या हर जगह एक readResolve() के लिए बेहतर समाधान प्रदान करता है। – eipark

1

cnull पर सेट किया जाएगा जब XML के पास c के लिए कोई मान सेट नहीं है। तब आप अपने गेटर में null के लिए जाँच और उचित डिफ़ॉल्ट मान लौट सकते हैं।

7

उपयोग PureJavaReflectionProvider

XStream xstream = new XStream(new PureJavaReflectionProvider()); 

और बस प्रारंभ हमेशा की तरह मूलभूत मूल्यों के साथ अपनी वस्तु। या तो फील्ड प्रारंभिकरण या कन्स्ट्रक्टर कोड के माध्यम से।

पृष्ठभूमि

आप एक ReflectionProvider Xstream निर्दिष्ट नहीं करते हैं सबसे अच्छा प्रतिबिंब प्रदाता खोजने की कोशिश करता। लेकिन Xstream के लिए सबसे अच्छा ReflectionProvider, आपके लिए सबसे अच्छा नहीं हो सकता है, क्योंकि यह सामान्य रूप से Sun14ReflectionProvider चयन करता है।

Sun14ReflectionProvider जावा क्रमबद्धता तंत्र के समान तत्काल रणनीति का उपयोग करता है और इसका मतलब है कि यह कन्स्ट्रक्टर कोड छोड़ देता है या अधिक विस्तृत होने के लिए - ऑब्जेक्ट प्रारंभकर्ता कोड।

इसलिए

class A { 
    private String b = "DEFAULT"; 
} 

लागू नहीं किया जाएगा और यह भी निर्माता कोड लागू नहीं किया जाएगा, जैसे जैसे उदाहरण क्षेत्र initializations

class A { 
    private String b; 

    public A(){ 
     b = "DEFAULT"; 
    } 
} 

PureJavaReflectionProvider बजाय का उपयोग करता है (जैसा कि नाम का तात्पर्य) जावा प्रतिबिंब एपीआई वस्तुओं, उदा का दृष्टांत को Class.newInstance() और इसलिए ऑब्जेक्ट प्रारंभिक कोड निष्पादित किया गया है।

+0

यह दृष्टिकोण काम नहीं करता है। यहां तक ​​कि PureJavaReflectionProvider डिफ़ॉल्ट मान को शून्य –

+0

के रूप में सेट करता है, यह स्कैला के साथ काम नहीं कर रहा है जहां कक्षा में डिफ़ॉल्ट मान निर्माता होता है, यानी कक्षा ए (स्ट्रिंग बी = "") – sowen

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