C# 使用JsonConverter存储/检索子-父关系
我有一个JSON结构(包括POCO类),子对象数组如下: "Object": [ { "Name": "TestA", "ChildObjects": [ { "Name": "TestB" "ChildObjects": [ { "Name": "TestC" ... } ] } ] “对象”:[ { “姓名”:“遗嘱”, “儿童对象”:[ { “名称”:“TestB” “儿童对象”:[ { “名称”:“TestC” ... } ] } ] 反序列化时,我希望保留对父级的引用 我刚刚创建的对象 但我必须在填充子对象之前获得此引用。(在填充子对象时,我必须访问父对象结构/引用) 我尝试过使用自定义JsonConverter,但是C# 使用JsonConverter存储/检索子-父关系,c#,json,json.net,C#,Json,Json.net,我有一个JSON结构(包括POCO类),子对象数组如下: "Object": [ { "Name": "TestA", "ChildObjects": [ { "Name": "TestB" "ChildObjects": [ { "Name": "TestC" ...
我找不到存储或检索此关系的方法。您不需要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; }
}
公共类OstacolisRuntime
{
public int codiceostatolo{get;set;}
公共int TipoOstacolo{get;set;}
公共int Tipologia{get;set;}
公共字符串Nome{get;set;}
公共双PosizioneX{get;set;}
公共双位置{get;set;}
公共双PosizioneZ{get;set;}
公共双AngoloX{get;set;}
公共双AngoloY{get;set;}
公共双AngoloZ{get;set;}
公共双ScalaX{get;set;}
公共双尺度{get;set;}
公共双标量{get;set;}
公共列表子目录{get;set;}//sub
}
公共类Subogetto
{
公共字符串Immagine{get;set;}
公共int Tipologia{get;set;}
公共字符串Nome{get;set;}
公共双PosizioneX{get;set;}
公共双位置{get;set;}
公共双PosizioneZ{get;set;}
公共双AngoloX{get;set;}
公共双AngoloY{get;set;}
公共双AngoloZ{get;set;}
公共双ScalaX{get;set;}
公共双尺度{get;set;}
公共双标量{get;set;}
公共列表子目录{get;set;}//递归relaship
}
公共类根对象
{
公共列表OstacolisRuntime{get;set;}
}
反序列化json:
var o= JsonConvert.DeserializeObject<RootObject>(json);
var o=JsonConvert.DeserializeObject(json);
您可以检查而不是将其定义为序列化问题(如何序列化和反序列化对父级的反向引用),将其定义为类设计问题可能是有意义的,即 给定父对象和子对象的层次结构,如何确保在将父对象添加到其父对象时,自动正确设置对父对象的子对象返回引用 一旦以这种方式定义并解决了问题,在反序列化和编程数据创建期间都应该确保正确性,因为父反向引用永远不需要序列化或反序列化 实现这一点的一种方法是定义的自定义子类,该子类自动设置和清除父反向引用 首先,定义以下接口和集合:
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);
}
}
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
是get only。Json.NET(以及IList ChildObjects
)可以成功地反序列化一个get only预分配的集合XmlSerializer
- 方法
是可选的,可防止对空shouldSerializedChildObjects()
数组值进行序列化ChildObjects[]
- 由于它本身是
的子类,因此如果在添加或删除项目时需要通知,可以选择它作为Collection
的基类ChildCollection
属性标记为,以防止其序列化Parent
示例包括一些基本单元测试。为了更清楚地理解dbc的答案,让我简化它 让我们以设置
RootObject
名为MyObject
的项的父对象为例:
{
"Object":[
{
"Name": "TestA"
}
]
}
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; }
}
定义集合:
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);
}
}
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);
}
}
您是否尝试将设置设置为
Objects
?如果这样做,您不需要转换器;引用将通过特殊的$id
和$ref
元属性保留在JSON中。@BrianRogers,我考虑过在“对象类”中添加一个“父对象”属性。这样我就可以获得对父节点的引用。您刚才告诉我的引用内容是否适合此用途?(如果它可以用作对JSON文件上父节点的引用)是的,您的子对象可以引用父对象,反之亦然,如果您在序列化和反序列化时都使用该设置,则应该可以使用该设置。您是否可以将您的问题共享(理想情况下简化)类型的版本——即a?我不清楚哪些类型对应于上面的JSON,哪些类型在创建过程中需要父节点。@dbc,它是doneM.Hassan。我已经有了这些类。我必须在反序列化时找到获得这种关系的方法。子节点必须能够在反序列化时知道父节点。