मैं जैकसन को एक संपत्ति की अनदेखी करने के लिए कैसे कह सकता हूं जिसके लिए मेरे पास स्रोत कोड पर नियंत्रण नहीं है?


112

लंबी कहानी संक्षेप में, मेरी एक संस्था में एक ज्योमेट्रीकोलेक्शन है जो एक अपवाद को फेंकता है जब आप "गेटबाउंडरी" कहते हैं (ऐसा क्यों होता है यह एक और पुस्तक है, अब हम कहते हैं कि यह काम करने का तरीका है)।

क्या कोई ऐसा तरीका है जिससे मैं जैक्सन को उस विशिष्ट गेट्टर को शामिल न कर सकूं? मुझे पता है कि जब मैं स्वयं कोड को नियंत्रित / नियंत्रित करूंगा तो मैं @JacksonIgnore का उपयोग कर सकता हूं। लेकिन यह मामला नहीं है, मूल वस्तुओं के निरंतर क्रमांकन के माध्यम से जैकसन इस बिंदु तक पहुंचता है। मैंने जैक्सन प्रलेखन में एक फ़िल्टरिंग विकल्प देखा। यह एक प्रशंसनीय समाधान है?

धन्यवाद!

जवाबों:


168

आप जैक्सन मिक्सिन्स का उपयोग कर सकते हैं । उदाहरण के लिए:

class YourClass {
  public int ignoreThis() { return 0; }    
}

इस मिक्सिन के साथ

abstract class MixIn {
  @JsonIgnore abstract int ignoreThis(); // we don't need it!  
}

इसके साथ:

objectMapper.getSerializationConfig().addMixInAnnotations(YourClass.class, MixIn.class);

संपादित करें:

टिप्पणियों के लिए धन्यवाद, जैक्सन 2.5+ के साथ, एपीआई बदल गया है और इसे बुलाया जाना चाहिए objectMapper.addMixIn(Class<?> target, Class<?> mixinSource)


1
और अगर संपत्ति मशीन से उत्पन्न होती है और उसके नाम में असमर्थित वर्ण होते हैं? पसंद '@'? JVM इसे अनुमति देता है, लेकिन जावा संकलक नहीं करता है। क्या इसके लिए जैक्सन के पास समाधान है?
मार्क

3
और objectMapper.addMixInAnnotations(Class<?> target, Class<?> mixinSource);
जैकसन

प्रॉपर्टी के नाम को पाने वाले के बजाय निर्दिष्ट करके मैं कैसे अनदेखा करूं?
एरान मुराद

68

एक अन्य संभावना है, यदि आप सभी अज्ञात गुणों को अनदेखा करना चाहते हैं, तो आप निम्नानुसार मैपर को कॉन्फ़िगर कर सकते हैं:

mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

5
यह बहुत अच्छा होगा यदि हम ऑब्जेक्टमैपर को केवल विशिष्ट संपत्तियों की अनदेखी करने के लिए कॉन्फ़िगर कर सकते हैं। यानी 'myfield' को छोड़कर सभी नए / अज्ञात क्षेत्रों के लिए अपवाद की रिपोर्ट करें। कुछ इस तरहmapper.configure(DeserializationFeature.failOnUnknownPropertiesExcep(new String[] {"myField"}));
ms_27

ध्यान दें कि यह भी एक रीडर पर कॉन्फ़िगर किया जा सकता है without()जैसे:mapper.reader().without(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
ड्रू स्टीफंस

मैं इस तंत्र का उपयोग करने के खिलाफ दृढ़ता से सलाह दूंगा। जैक्सन में "सख्त" मानसिकता, जिसके कारण अज्ञात / अखंडित क्षेत्रों पर त्रुटियों को उठाया जा सकता है, इसकी ताकत में से एक है और जावा के सांख्यिकीय रूप से टाइप / संकलित-समय-विश्लेषण की प्रकृति से मेल खाती है। इसके बजाय बेहतर है कि अनदेखा किए गए क्षेत्रों के दिए गए सेट को संभालने से बचें।
प्रति लुंडबर्ग

26

जावा क्लास का उपयोग करना

new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)

एनोटेशन का उपयोग करना

@JsonIgnoreProperties(ignoreUnknown=true)

11

एनोटेशन आधारित दृष्टिकोण बेहतर है। लेकिन कभी-कभी मैनुअल ऑपरेशन की जरूरत होती है। इस उद्देश्य के लिए आप बिना ObjectWriter के विधि का उपयोग कर सकते हैं ।

ObjectMapper mapper   = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
ObjectWriter writer   = mapper.writer().withoutAttribute("property1").withoutAttribute("property2");
String       jsonText = writer.writeValueAsString(sourceObject);

9
यह दृष्टिकोण मेरे लिए काम नहीं करता है, लेकिन मिश्रण एक करता है। मुझे अभी भी सीरियल करने के बाद नजरअंदाज किए गए गुण मिलते हैं। जब हमारे पास बिना आढ़ती () हो तो हमारे पास मिक्सी क्यों है?
एर्रान मोरड

9

मिक्स-इन एनोटेशन यहाँ पहले से ही उल्लेख किया गया है। प्रति-संपत्ति @JsonIgnore से परे एक और संभावना @JsonIgnoreType का उपयोग करने के लिए है यदि आपके पास एक प्रकार है जिसे कभी भी शामिल नहीं किया जाना चाहिए (यानी यदि ज्यामिति के सभी उदाहरणों को अनदेखा किया जाना चाहिए)। आप इसे या तो सीधे जोड़ सकते हैं (यदि आप प्रकार को नियंत्रित करते हैं), या मिक्स-इन का उपयोग करके, जैसे:

@JsonIgnoreType abstract class MixIn { }
// and then register mix-in, either via SerializationConfig, or by using SimpleModule

यह अधिक सुविधाजनक हो सकता है यदि आपके पास बहुत सारी कक्षाएं हैं जिनमें सभी के पास एक ही 'इग्नोरटाइप getContext ()' एक्सेसर या (जो कि कई रूपरेखाओं के लिए मामला है)


5

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

public class A{
  Long id;
  String name;
  List<B> children;
}

public class B{
  Long id;
  A parent;
}

parentअगर मैं ए को देख रहा हूं, तो मैं प्रोग्राम को बी में फील्ड को नजरअंदाज करना चाहूंगा और childrenअगर मैं बी को देख रहा हूं तो ए में फील्ड को नजरअंदाज कर दूंगा ।

मैंने ऐसा करने के लिए मिश्रणों का उपयोग करना शुरू कर दिया, लेकिन यह बहुत जल्दी भयानक हो जाता है; आपके पास बहुत सारे बेकार वर्ग हैं जो केवल डेटा को प्रारूपित करने के लिए मौजूद हैं। : मैं एक क्लीनर तरीके से इस संभाल करने के लिए अपने खुद के serializer लेखन समाप्त हो गया https://github.com/monitorjbl/json-view

यह आपको प्रोग्राम करने की अनुमति देता है कि किन क्षेत्रों को अनदेखा करें:

ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addSerializer(JsonView.class, new JsonViewSerializer());
mapper.registerModule(module);

List<A> list = getListOfA();
String json = mapper.writeValueAsString(JsonView.with(list)
    .onClass(B.class, match()
        .exclude("parent")));

यह आपको वाइल्डकार्ड मैचर्स के माध्यम से आसानी से बहुत सरल दृष्टिकोण बताने की सुविधा देता है:

String json = mapper.writeValueAsString(JsonView.with(list)
    .onClass(A.class, match()
        .exclude("*")
         .include("id", "name")));

मेरे मूल मामले में, माता-पिता / बच्चे के बारे में नंगे न्यूनतम दिखाने के लिए इस तरह के सरल विचारों की आवश्यकता थी, लेकिन यह हमारी भूमिका-आधारित सुरक्षा के लिए भी उपयोगी हो गया। ऑब्जेक्ट के बारे में कम जानकारी वापस करने के लिए आवश्यक वस्तुओं के कम विशेषाधिकार प्राप्त विचार।

यह सब धारावाहिक से आता है, लेकिन मैं अपने ऐप में स्प्रिंग एमवीसी का उपयोग कर रहा था। इन मामलों को ठीक से संभालने के लिए, मैंने एक एकीकरण लिखा है जिसे आप मौजूदा स्प्रिंग नियंत्रक कक्षाओं में छोड़ सकते हैं:

@Controller
public class JsonController {
  private JsonResult json = JsonResult.instance();
  @Autowired
  private TestObjectService service;

  @RequestMapping(method = RequestMethod.GET, value = "/bean")
  @ResponseBody
  public List<TestObject> getTestObject() {
    List<TestObject> list = service.list();

    return json.use(JsonView.with(list)
        .onClass(TestObject.class, Match.match()
            .exclude("int1")
            .include("ignoredDirect")))
        .returnValue();
  }
}

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


आयात किस लिए होता है Match.match()?
पसुपति राजमनिकम

2

यदि आप किसी वर्ग के लिए कुछ गुणों को अलग करना चाहते हैं, तो आप setMixInResolverविधि का उपयोग कर सकते हैं :

    @JsonIgnoreProperties({"id", "index", "version"})
    abstract class MixIn {
    }

    mapper.setMixInResolver(new ClassIntrospector.MixInResolver(){
        @Override
        public Class<?> findMixInClassFor(Class<?> cls) {
            return MixIn.class;  
        }

        @Override
        public ClassIntrospector.MixInResolver copy() {
            return this;
        }
    });

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.