2013-08-27 9 views
8

मेरे पास एक ऑब्जेक्ट है जिसमें कई गुण हैं जो तारों की सूची List<String> या तारों का एक शब्दकोश Dictionary<string,string> है। मैं जेसननेट का उपयोग कर जेसन को ऑब्जेक्ट को क्रमबद्ध करना चाहता हूं और मैं कम से कम पाठ उत्पन्न करना चाहता हूं।खाली संग्रहों के जेसननेट को छोड़ने के लिए कैसे करें

मैं डिफॉल्ट वैल्यू हैंडलिंग और नलवैल्यू हैंडलिंग का उपयोग कर रहा हूं ताकि डिफ़ॉल्ट मान स्ट्रिंग्स और पूर्णांक पर सेट कर सकें। लेकिन अगर मैं रिक्त List<String> या Dictionary<string,string> पर प्रारंभ किया गया है, तो मैं धारावाहिक आउटपुट में संपत्ति को अनदेखा करने के लिए DefaultValueHandling को परिभाषित कैसे कर सकता हूं?

कुछ नमूना उत्पादन होता है:

{ 
"Value1": "my value", 
"Value2": 3, 
"List1": [], 
"List2": [] 
} 

मैं एक परिणाम है कि ऊपर के उदाहरण में दो सूचियों पर ध्यान नहीं देता, क्योंकि वे एक खाली सूची के डिफ़ॉल्ट मान पर सेट कर रहे हैं करना चाहते हैं।

किसी भी मदद

+0

मुझे नहीं लगता कि यह संभव है। मुझे यकीन है कि 'शून्य' मानों को अनदेखा करना बहुत कठिन नहीं होगा, लेकिन आपको अन्यत्र परिवर्तन करने की आवश्यकता होगी ताकि वे संदर्भ रिक्त सूची को इंगित करने के बजाय शून्य हों। – evanmcdonnal

+0

मुझे यकीन है कि यह एक कस्टम कनवर्टर (अमूर्त वर्ग जेसन कनवर्टर को कार्यान्वित करके) के साथ किया जा सकता है, लेकिन अब मैं कोड प्रदान करने के लिए बहुत आलसी हूं। – I4V

+0

मुझे यह आलेख मिला जिसमें IContractResolver का संदर्भ शामिल है। http://james.newtonking.com/archive/2009/10/23/efficient-json-with-json-net-reducing-serialized-json-size.aspx यह लागू करने का एक तरीका खोजने के लिए एक अच्छा सीसा प्रतीत होता है इस। – agarcian

उत्तर

10

मैं अपने निजी रूपरेखा (specific commit मामले में फ़ाइल बाद में ले जाया जाएगा के लिए लिंक) के custom contract resolver में इस सुविधा को लागू किया है की सराहना की जाएगी। यह कुछ सहायक तरीकों का उपयोग करता है और कस्टम संदर्भ वाक्यविन्यास के लिए कुछ असंबंधित कोड भी शामिल करता है। उनके बिना, कोड होगा:

public class SkipEmptyContractResolver : DefaultContractResolver 
{ 
    public SkipEmptyContractResolver (bool shareCache = false) : base(shareCache) { } 

    protected override JsonProperty CreateProperty (MemberInfo member, 
      MemberSerialization memberSerialization) 
    { 
     JsonProperty property = base.CreateProperty(member, memberSerialization); 
     bool isDefaultValueIgnored = 
      ((property.DefaultValueHandling ?? DefaultValueHandling.Ignore) 
       & DefaultValueHandling.Ignore) != 0; 
     if (isDefaultValueIgnored 
       && !typeof(string).IsAssignableFrom(property.PropertyType) 
       && typeof(IEnumerable).IsAssignableFrom(property.PropertyType)) { 
      Predicate<object> newShouldSerialize = obj => { 
       var collection = property.ValueProvider.GetValue(obj) as ICollection; 
       return collection == null || collection.Count != 0; 
      }; 
      Predicate<object> oldShouldSerialize = property.ShouldSerialize; 
      property.ShouldSerialize = oldShouldSerialize != null 
       ? o => oldShouldSerialize(o) && newShouldSerialize(o) 
       : newShouldSerialize; 
     } 
     return property; 
    } 
} 

यह अनुबंध समाधानकर्ता सभी खाली संग्रह में से क्रमबद्धता को छोड़ देगा (सभी प्रकार ICollection लागू करने और Length == 0 वाले), जब तक DefaultValueHandling.Include संपत्ति या क्षेत्र के लिए निर्दिष्ट किया जाता है।

+0

हाँप !!! वह वास्तव में काम करता है। धन्यवाद। – agarcian

+0

मुझे लगता है कि आप 'objectProp' और' memberField' की आवश्यकता को 'ऑब्जेक्ट वैल्यू = property.ValueProvider.GetValue (obj) कर कर हटा सकते हैं; '। – Quartermeister

+0

@Quartermeister सुझाव के लिए धन्यवाद, अद्यतन। – Athari

6

एक और बहुत ही सरल समाधान ShouldSerialize* विधि को आउटलाइन here के रूप में क्रमबद्ध करने के प्रकार को कार्यान्वित करना है।

यदि आप धारावाहिक प्रकार के नियंत्रण में हैं और यदि यह एक सामान्य व्यवहार नहीं है जिसे आप पेश करना चाहते हैं तो यह पसंदीदा तरीका हो सकता है।

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