2014-09-15 3 views
16

मेरे पास दोगुनी सूची है जो मैं deserialise करने की कोशिश कर रहा हूँ।जेएसओएन। संरक्षित संदर्भों का सम्मान नहीं करते हैं Deserialization पर हैंडलिंग

मेरे परिदृश्य बारीकी से इस अतः से संबंधित है: Doubly Linked List to JSON

मैं निम्नलिखित JSON सेटिंग है:

_jsonSettings = new JsonSerializerSettings() 
{ 
    TypeNameHandling = TypeNameHandling.Auto, 
    ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor, 
    PreserveReferencesHandling = PreserveReferencesHandling.Objects, 
    ObjectCreationHandling = ObjectCreationHandling.Auto 
}; 

जब मैं धारावाहिक उत्पादन को देखो, यह सही प्रतीत होता है, और नोड्स के बीच संदर्भ ठीक से कर रहे हैं का प्रतिनिधित्व किया।

जब डेटा deserialised है, बाल वस्तुओं में अभिभावक गुण शून्य हैं, भले ही वे सही ढंग से $ ref के साथ आबादी वाले हैं।

नीचे JSON (पठनीयता के लिए छंटनी की) इस सवाल टाइपिंग की प्रक्रिया में

का एक नमूना है - मैं मुसीबत का स्रोत ...

"बच्चों में वस्तुओं देखा हो सकता है "सरणी संपत्ति में $ प्रकार विशेषता नहीं है।

यह हो सकता है क्योंकि बच्चे और माता पिता के गुण सामान्य प्रकार टी के हैं

ध्यान दें कि वास्तविक प्रकार धारावाहिक की जा रही TemplateDataLinkedListBase

public class TemplateDataQueryElement : TemplateDataLinkedListBase<TemplateDataQueryElement> 

यहाँ की एक व्युत्पन्न वर्ग आधार का एक अंश है वर्ग:

public class TemplateDataLinkedListBase<T> where T : TemplateDataLinkedListBase<T> 
{ 
    [JsonProperty(TypeNameHandling = TypeNameHandling.Objects)] 
    public T Parent { get; set; } 

    [JsonProperty(TypeNameHandling=TypeNameHandling.Objects)] 
    public List<T> Children { get; set; } 
} 

मैं कैसे इस तरह से इस JSON deserialise सकते हैं कि जनक संपत्ति रिक्त नहीं है और एक संदर्भ th करने के लिए होता है ई पैरेंट ऑब्जेक्ट?

{ 
    "$id": "9", 
    "$type": "Contracts.Models.TemplateDataQueryElement, Contracts", 
    "Query": null, 
    "Parent": null, 
    "Children": [ 
     { 
     "$id": "11", 
     "Query": null, 
     "Parent": { 
      "$ref": "9" 
     }, 
     "Children": [ 
      { 
      "$id": "13", 
      "Query": null, 
      "Parent": { 
       "$ref": "11" 
      }, 
      "Children": [], 
      "EntityName": "Widgets", 
      "Fields": [ 
       "Id" 
      ], 
      "Key": "" 
      }, 

यहाँ प्रासंगिक कोड को pastebin लिंक कर रहे हैं:

http://pastebin.com/i1jxVGG3 http://pastebin.com/T1xqEWW2 http://pastebin.com/ha42SeF7 http://pastebin.com/cezwZqx6 http://pastebin.com/uFbTbUZe http://pastebin.com/sRhNQgzh

+0

क्या आप क्या कर रहे हैं पर बेहतर समझने के लिए पूरी कक्षा परिभाषा पोस्ट कर सकते हैं? –

+0

और यह भी एक उदाहरण है कि आप धारावाहिकरण और deserialization कैसे कर रहे हैं? –

+0

हाय @IlijaDimov मैंने स्रोत कोड – RobD

उत्तर

15

यहाँ मैं क्या करने की कोशिश की और ठीक काम किया है:

कक्षाएं

public class TemplateDataLinkedListBase<T> where T : TemplateDataLinkedListBase<T> 
{ 
    [JsonProperty(TypeNameHandling = TypeNameHandling.Objects)] 
    public T Parent { get; set; } 

    [JsonProperty(TypeNameHandling = TypeNameHandling.Objects)] 
    public List<T> Children { get; set; } 
} 

public class TemplateDataQueryElement : TemplateDataLinkedListBase<TemplateDataQueryElement> 
{ 
    public string Query { get; set; } 

    public TemplateDataQueryElement() 
    { 
     Children = new List<TemplateDataQueryElement>(); 
    } 
} 

प्रारंभ

var childLowest = new TemplateDataQueryElement 
{ 
    Query = "Lowest" 
}; 

var childMiddle = new TemplateDataQueryElement 
{ 
    Query = "Middle", 
    Children = new List<TemplateDataQueryElement> 
    { 
     childLowest 
    } 
}; 

childLowest.Parent = childMiddle; 

var parent = new TemplateDataQueryElement 
{ 
    Query = "Parent", 
    Children = new List<TemplateDataQueryElement> 
    { 
     childMiddle 
    } 
}; 

childMiddle.Parent = parent; 

क्रमबद्धता सेटिंग्स

var _jsonSettings = new JsonSerializerSettings() 
{ 
    TypeNameHandling = TypeNameHandling.Auto, 
    ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor, 
    PreserveReferencesHandling = PreserveReferencesHandling.Objects, 
    ObjectCreationHandling = ObjectCreationHandling.Auto 
}; 

क्रमबद्धता

var serializedStr = JsonConvert.SerializeObject(parent, Formatting.Indented, _jsonSettings); 

धारावाहिक json इस तरह दिखता है:

{ 
    "$id": "1", 
    "Query": "Parent", 
    "Parent": null, 
    "Children": [ 
    { 
     "$id": "2", 
     "Query": "Middle", 
     "Parent": { 
     "$ref": "1" 
     }, 
     "Children": [ 
     { 
      "$id": "3", 
      "Query": "Lowest", 
      "Parent": { 
      "$ref": "2" 
      }, 
      "Children": [] 
     } 
     ] 
    } 
    ] 
} 

Deserialization

var deserializedStructure = JsonConvert.DeserializeObject<TemplateDataQueryElement>(serializedStr, _jsonSettings); 

deserializedStructure में संदर्भ सही ढंग से संरक्षित कर रहे हैं।

डेमो https://dotnetfiddle.net/j1Qhu6

अद्यतन 1

कारण मेरी उदाहरण काम करता है, और कोड आप अतिरिक्त लिंक में पोस्ट नहीं है क्योंकि मेरी कक्षाओं डिफ़ॉल्ट निर्माता, और तुम्हारा डॉन शामिल 'टी। अपने वर्गों का विश्लेषण करना, उनके लिए एक डिफ़ॉल्ट कन्स्ट्रक्टर जोड़ना, यह कार्यक्षमता को तोड़ नहीं देगा और deserialization Parent संपत्ति के साथ सफलतापूर्वक शुरू हो जाएगा। तो क्या आप मूल रूप से करने की जरूरत है दोनों वर्गों के लिए एक डिफ़ॉल्ट निर्माता को जोड़ने है:

public class TemplateDataLinkedListBase<T> where T : TemplateDataLinkedListBase<T> 
{ 
    [JsonProperty(TypeNameHandling = TypeNameHandling.Objects)] 
    public T Parent { get; set; } 

    [JsonProperty(TypeNameHandling=TypeNameHandling.Objects)] 
    public List<T> Children { get; set; } 
    public string EntityName { get; set; } 
    public HashSet<string> Fields { get; set; } 

    public string Key { get { return getKey(); } } 


    public TemplateDataLinkedListBase() 
    { 
     Children = new List<T>(); 
     Fields = new HashSet<string>(); 
    } 

    public TemplateDataLinkedListBase(string entityName) 
    { 
     EntityName = entityName; 
     Children = new List<T>(); 
     Fields = new HashSet<string>(); 
    } 

    private string getKey() 
    { 
     List<string> keys = new List<string>(); 
     keys.Add(this.EntityName); 
     getParentKeys(ref keys, this); 
     keys.Reverse(); 
     return string.Join(".", keys); 

    } 

    private void getParentKeys(ref List<string> keys, TemplateDataLinkedListBase<T> element) 
    { 
     if (element.Parent != null) 
     { 
      keys.Add(element.Parent.EntityName); 
      getParentKeys(ref keys, element.Parent); 
     } 
    } 

    public T AddChild(T child) 
    { 
     child.Parent = (T)this; 
     Children.Add(child); 
     return (T)this; 
    } 

    public T AddChildren(List<T> children) 
    { 
     foreach (var child in children) 
     { 
      child.Parent = (T)this; 
     } 
     Children.AddRange(children); 
     return (T)this; 
    } 

    public void AddFields(IEnumerable<string> fields) 
    { 
     foreach (var field in fields) 
      this.Fields.Add(field); 
    } 

    public TemplateDataLinkedListBase<T> Find(string searchkey) 
    { 
     if (this.Key == searchkey) 
     { 
      return this; 
     } 
     else 
     { 
      foreach (var child in Children) 
      { 
       if (child.Key == searchkey) 
       { 
        return child; 
       } 
       else 
       { 
        var childResult = child.Find(searchkey); 
        if (childResult != null) return childResult; 
       } 
      } 
     } 
     return null; 
    } 
} 

public class TemplateDataQueryElement : TemplateDataLinkedListBase<TemplateDataQueryElement>, ITemplateDataQueryElement 
{ 
    public string TemplateModelName { get; set; } 
    public string RecordId { get; set; } 
    public string ParentForeignKeyName { get; set; } 
    public string Query { get; set; } 
    public dynamic ObjectData { get; set; } 
    public ITemplateDataParseResult ParseResult { get; set; } 


    public TemplateDataQueryElement() : base() 
    { 
     Fields.Add("Id"); //Always retrieve Id's 
     ObjectData = new ExpandoObject(); 
    } 

    public TemplateDataQueryElement(string entityName) 
     : base(entityName) 
    { 
     Fields.Add("Id"); //Always retrieve Id's 
     ObjectData = new ExpandoObject(); 
    } 

    public override string ToString() 
    { 
     return string.Format("{0}: {1}", EntityName, Query); 
    } 
} 

EntityName संपत्ति जो आप अपने निर्माता के माध्यम से निर्धारित करते हैं, सही ढंग से deserialized किया जाएगा, क्योंकि यह एक सार्वजनिक संपत्ति है।

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