我有一个带有子对象数组的JSON结构(包括POCO类),如下所示:
"Object": [ { "Name": "TestA", "ChildObjects": [ { "Name": "TestB" "ChildObjects": [ { "Name": "TestC" ... } ] } ]
反序列化时,我想保留对父级的引用 对象我刚刚创建。
但是我必须在填充子对象之前得到这个引用。(在我填充子对象的那一刻,我必须有父对象结构/引用可访问)。
我尝试过使用自定义JsonConverter,但是 我找不到存储或检索这种关系的方法。
答案 0 :(得分:2)
不是将其定义为序列化问题(如何序列化和反序列化对父项的反向引用),将其定义为类设计问题可能是有意义的,即
鉴于父母和子女的等级,如何确保在向父母添加父母时,自动正确设置对父母的反对引用?
一旦问题以这种方式定义并解决,在反序列化期间和程序化数据创建期间都应该确保正确性,因为父反向引用永远不需要被序列化或反序列化。
实现此目的的一种方法是定义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);
}
}
然后按如下方式定义您的MyObject
和RootObject
类型:
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> ChildObjects
中的集合MyObject
是get-only。 Json.NET(以及XmlSerializer
就此而言)可以成功地反序列化一个只用于预分配的集合。
方法ShouldSerializeChildObjects()
是可选的,可防止序列化空的ChildObjects []
数组值。
由于ObservableCollection<T>
本身是Collection<T>
的子类,如果在添加或删除项目时需要通知,则可以选择它作为ChildCollection<TParent, TChild>
的基类。
Parent
属性标有[JsonIgnore]
以阻止其序列化。
示例fiddle包括一些基本的单元测试。
答案 1 :(得分: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
答案 2 :(得分:0)
为了更清楚地理解dbc的答案,让我简化一下。
我们以为RootObject
的名为MyObject
的项目设置父级为例:
{
"Object":[
{
"Name": "TestA"
}
]
}
定义集合:
public class Items : Collection<MyObject>
{
private RootObject Owner;
public Items(RootObject owner)
{
Owner = owner;
}
protected override void InsertItem(int index, MyObject item)
{
item.Parent = Owner;
base.InsertItem(index, item);
}
}
定义MyObject
和RootObject
:
public class MyObject
{
[JsonIgnore]
public RootObject Parent { get; set; }
public string Name { get; set; }
}
public class RootObject
{
public RootObject() { ChildObjects = new Items(this); }
public Items ChildObjects { get; }
}