2014-11-15 8 views
18

मैं एक पीओजेओ कक्षा को क्रमबद्ध करना चाहता हूं जो मेरे नियंत्रण में नहीं है, लेकिन सुपरक्लास से आने वाली किसी भी संपत्ति को क्रमबद्ध करने से बचाना चाहता है, न कि अंतिम कक्षा से। उदाहरण:जैक्सन क्रमबद्धता: सुपरक्लास गुणों को अनदेखा करने के लिए कैसे करें

public class MyGeneratedRecord extends org.jooq.impl.UpdatableRecordImpl<...>, 
    example.generated.tables.interfaces.IMyGenerated { 
    public void setField1(...); 
    public Integer getField1(); 

    public void setField2(...); 
    public Integer getField2(); 
... 
} 

आप उदाहरण है कि कि इस वर्ग के JOOQ द्वारा उत्पन्न होता है, और एक जटिल आधार वर्ग UpdatableRecordImpl जो भी कुछ सेम संपत्ति की तरह विधियों, जो क्रमबद्धता के दौरान समस्याओं का कारण है से विरासत से अनुमान लगा सकते हैं। इसके अलावा, मेरे पास कई समान वर्ग हैं, इसलिए मेरे सभी जेनरेट किए गए पीओजेओ के लिए एक ही समाधान को डुप्लिकेट करना टालना अच्छा होगा।

मैं अब तक संभव समाधान निम्नलिखित पाया है:

  • विशिष्ट क्षेत्रों इस तरह mixin तकनीक का उपयोग कर सुपर क्लास से आ रही उपेक्षा: How can I tell jackson to ignore a property for which I don't have control over the source code?

    इस के साथ समस्या यह है कि अगर आधार वर्ग परिवर्तन (उदाहरण के लिए, इसमें एक नई getAnything() विधि दिखाई देती है), यह मेरे कार्यान्वयन को तोड़ सकता है।

  • कस्टम सीरिएलाइज़र को लागू करें और वहां समस्या को संभालें। यह मेरे लिए थोड़ा अधिक लगता है।

  • के रूप में संयोग से मेरे पास है एक अंतरफलक जो वास्तव में गुण मैं क्रमानुसार करने चाहते हैं, हो सकता है मैं एक @JsonSerialize Mixin कर सकते हैं का वर्णन करता है (= IMyGenerated.class के रूप में) एनोटेशन ...? क्या मैं इसे अपने उद्देश्य के लिए उपयोग कर सकता हूं?

लेकिन, देखने के शुद्ध डिजाइन बिंदु से, सबसे अच्छा जैक्सन बताते हैं कि मैं केवल अंतिम वर्ग 'गुण क्रमानुसार करने चाहते हैं, और सभी विरासत में मिला है लोगों की उपेक्षा करने में सक्षम होना होगा। क्या ऐसा करने के लिए कोई रास्ता है?

अग्रिम धन्यवाद।

उत्तर

15

आप एक कस्टम Jackson annotation intropector पंजीकृत कर सकते हैं जो कुछ सुपर प्रकारों से आने वाली सभी संपत्तियों को अनदेखा कर देगा। यहाँ एक उदाहरण है:

public class JacksonIgnoreInherited { 

    public static class Base { 
     public final String field1; 

     public Base(final String field1) { 
      this.field1 = field1; 
     } 
    } 

    public static class Bean extends Base { 
     public final String field2; 

     public Bean(final String field1, final String field2) { 
      super(field1); 
      this.field2 = field2; 
     } 
    } 

    private static class IgnoreInheritedIntrospector extends JacksonAnnotationIntrospector { 
     @Override 
     public boolean hasIgnoreMarker(final AnnotatedMember m) { 
      return m.getDeclaringClass() == Base.class || super.hasIgnoreMarker(m); 
     } 
    } 

    public static void main(String[] args) throws JsonProcessingException { 
     final ObjectMapper mapper = new ObjectMapper(); 
     mapper.setAnnotationIntrospector(new IgnoreInheritedIntrospector()); 
     final Bean bean = new Bean("a", "b"); 
     System.out.println(mapper 
         .writerWithDefaultPrettyPrinter() 
         .writeValueAsString(bean)); 
    } 

} 

आउटपुट:

{ "field2": "ख" }

+1

जैक्सन अनुकूलन संभावनाओं के असंख्य के साथ एक अद्भुत पुस्तकालय है। यह हमेशा मुझे गूंगा महसूस करता है क्यों मुझे अपने कस्टम व्यवहार को हुक करने के लिए उचित जगह नहीं मिलती हैं। :) धन्यवाद, मुझे यही चाहिए! – Ferenc

+0

समाधान आवश्यक परिणाम प्राप्त करता है, लेकिन यह धारावाहिक गुणों की सूची को जानना मुश्किल बनाता है या बनाता है। – jordiburgos

+2

यह समाधान मेरे लिए काम किया। जटिल JOOQ बेस क्लास को बहुत अनदेखा करते हैं, मेरे '' 'IgnoreMarker'' कार्यान्वयन' '' वापसी m.getDeclaringClass() है getName()। ("Org.jooq") || super.hasIgnoreMarker (एम) '' ' – Nathan

2

विरासत का अच्छा उपयोग यह है कि बाल वर्ग विस्तार या कार्यक्षमता जोड़ते हैं। तो सामान्य तरीका डेटा को क्रमबद्ध करना है।

एक वर्कअराउंड एक मूल्य वस्तु (वीओ) या डेटा ट्रांसफर ऑब्जेक्ट (डीटीओ) का उपयोग उन क्षेत्रों के साथ करना होगा जिन्हें आपको क्रमबद्ध करने की आवश्यकता है। चरण:

  • धारावाहिक होने वाले फ़ील्ड के साथ एक वीओ कक्षा बनाएं।
  • गुणों की प्रतिलिपि बनाने के लिए BeanUtils.copyProperties (लक्ष्य VO, स्रोत डेटा) का उपयोग करें
  • वीओ उदाहरण को क्रमबद्ध करें।
+0

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

+0

अन्यथा, आपको बच्चे वर्ग पर फ़ील्ड को फिर से परिभाषित करने की आवश्यकता है और इसे "धारावाहिक नहीं" के रूप में चिह्नित करें। – jordiburgos

+1

@ फ़ेरेनक: आप jOOQ आपके लिए उन सभी POJOs/VOs/DTO उत्पन्न कर सकते हैं: http://www.jooq.org/doc/latest/manual/code-generation/codegen-pojos/ –

3

आप सुपर क्लास 'तरीकों जो आप उत्पादन होने से रोकना चाहते हैं ओवरराइड कर सकते हैं और @JsonIgnore के साथ उन्हें एनोटेट करें। ओवरराइड संपत्ति निर्माण के नियंत्रण को उप-वर्ग में बदल देता है जबकि इसे आउटपुट से फ़िल्टर करने की क्षमता सक्षम करता है।

उदाहरण के लिए:

public class SomeClass { 
    public void setField1(...); 
    public Integer getField1(); 

    public void setField2(...); 
    public Integer getField2(); 

    @Override 
    @JsonIgnore 
    public String superClassField1(...){ 
     return super.superClassField1(); 
    }; 

    @Override 
    @JsonIgnore 
    public String superClassField2(...){ 
     return super.superClassField2(); 
    }; 
... 
} 
संबंधित मुद्दे