2017-10-16 83 views
1

我有一个JSON结构(包括POCO类)与亲子关系的孩子的对象数组是这样的:存储/检索与JsonConverter

 

    "Object": [ 
    { 
     "Name": "TestA", 
     "ChildObjects": [ 
     { 
      "Name": "TestB" 
      "ChildObjects": [ 
       { 
        "Name": "TestC" 
        ... 
       } 
      ] 
     } 
    ] 

反序列化的时候,我想引用保持父 我刚刚创建的对象。

但是我必须在填充子对象之前得到这个引用(当我填充子对象时,我必须有父对象结构/引用可访问)

我试过使用自定义的JsonConverter,但是 我找不到存储或检索这种关系的方法。

+1

您是否尝试将['PreserveReferencesHandling'](https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_PreserveReferencesHandling.htm)设置设置为'Objects'?如果你这样做,你不应该需要一个转换器;引用将通过特殊的'$ id'和'$ ref'元属性保存在JSON中。 –

+0

@BrianRogers,我想过为“Object Class”添加一个“Parent Object”属性。这样我就可以得到父母的参考。这个参考资料是否适合这种用途? (如果它可以作为JSON文件上父节点的引用) –

+0

是的,您的子对象可以引用父对象,反之亦然,如果您在序列化和反序列化时都使用该设置,它应该可以工作。 –

回答

0

你不需要JsonConverter。

您可以创建表示JSON,下面给出的POCO类:

public class OstacolisRuntime 
    { 
     public int CodiceOstacolo { get; set; } 
     public int TipoOstacolo { get; set; } 
     public int Tipologia { get; set; } 
     public string Nome { get; set; } 
     public double PosizioneX { get; set; } 
     public double PosizioneY { get; set; } 
     public double PosizioneZ { get; set; } 
     public double AngoloX { get; set; } 
     public double AngoloY { get; set; } 
     public double AngoloZ { get; set; } 
     public double ScalaX { get; set; } 
     public double ScalaY { get; set; } 
     public double ScalaZ { get; set; } 
     public List<SubOggetto> SubOggettos { get; set; } //sub 
    } 




    public class SubOggetto 
    { 
     public string Immagine { get; set; } 
     public int Tipologia { get; set; } 
     public string Nome { get; set; } 
     public double PosizioneX { get; set; } 
     public double PosizioneY { get; set; } 
     public double PosizioneZ { get; set; } 
     public double AngoloX { get; set; } 
     public double AngoloY { get; set; } 
     public double AngoloZ { get; set; } 
     public double ScalaX { get; set; } 
     public double ScalaY { get; set; } 
     public double ScalaZ { get; set; } 
     public List<SubOggetto> SubOggettos { get; set; } //recursive relashioship 
    } 


    public class RootObject 
    { 
     public List<OstacolisRuntime> OstacolisRuntime { get; set; } 
    } 

反序列化您JSON:

var o= JsonConvert.DeserializeObject<RootObject>(json); 

您可以检查complete source code

+0

M.哈桑。我已经有了这些课程。反序列化时,我必须找到一种方法来获得这种关系。子节点必须能够在反序列化中知道父节点。 –

0

而不是定义这是一个序列化问题(如何序列化和反序列化对父代的反向引用),将其定义为类设计问题可能是有意义的,即

由于家长和孩子的层次结构,如何保证孩子的父母背引用自动将其添加到他们的父母时设置是否正确?

一旦以这种方式定义问题并解决问题,在反序列化和程序化数据创建期间应保证正确性,因为父反向引用永远不需要序列化或反序列化。

完成此操作的一种方法是定义一个自定义子类Collection<T>,该子类自动设置并清除父回引用。

首先,定义以下接口和收集:

public interface IHasParent<TParent> where TParent : class 
{ 
    TParent Parent { get; } 

    void OnParentChanging(TParent newParent); 
} 

public class ChildCollection<TParent, TChild> : Collection<TChild> 
    where TChild : IHasParent<TParent> 
    where TParent : class 
{ 
    readonly TParent parent; 

    public ChildCollection(TParent parent) 
    { 
     this.parent = parent; 
    } 

    protected override void ClearItems() 
    { 
     foreach (var item in this) 
     { 
      if (item != null) 
       item.OnParentChanging(null); 
     } 
     base.ClearItems(); 
    } 

    protected override void InsertItem(int index, TChild item) 
    { 
     if (item != null) 
      item.OnParentChanging(parent); 
     base.InsertItem(index, item); 
    } 

    protected override void RemoveItem(int index) 
    { 
     var item = this[index]; 
     if (item != null) 
      item.OnParentChanging(null); 
     base.RemoveItem(index); 
    } 

    protected override void SetItem(int index, TChild item) 
    { 
     var oldItem = this[index]; 
     if (oldItem != null) 
      oldItem.OnParentChanging(null); 
     if (item != null) 
      item.OnParentChanging(parent); 
     base.SetItem(index, item); 
    } 
} 

然后定义您的MyObjectRootObject类型如下:

public class MyObject : IHasParent<MyObject> 
{ 
    readonly ChildCollection<MyObject, MyObject> childObjects; 

    public MyObject() { this.childObjects = new ChildCollection<MyObject, MyObject>(this); } 

    public string Name { get; set; } 

    public IList<MyObject> ChildObjects { get { return childObjects; } } 

    #region IHasParent<MyObject> Members 

    [JsonIgnore] 
    public MyObject Parent { get; private set; } 

    public void OnParentChanging(MyObject newParent) 
    { 
     Parent = newParent; 
    } 

    #endregion 

    // Added to suppress serialization of empty ChildObjects collections to JSON. 
    public bool ShouldSerializeChildObjects() { return childObjects.Count > 0; } 
} 

public class RootObject 
{ 
    public RootObject() { this.Object = new List<MyObject>(); } 

    public List<MyObject> Object { get; set; } 
} 

注:

  • 收集IList<MyObject> ChildObjectsMyObject是启动LY。 Json.NET(和XmlSerializer就此而言)可以成功反序列化一个只能获得预分配的集合。

  • 方法ShouldSerializeChildObjects()是可选的,并防止对空的ChildObjects []数组值进行序列化。

  • 由于ObservableCollection<T>本身就是Collection<T>一个子类,你可以选择它作为基类为ChildCollection<TParent, TChild>,如果你需要通知项目时添加或删除。

  • Parent属性标有[JsonIgnore]以防止其序列化。

样本fiddle包括一些基本的单元测试。