当我从 Json.net 反序列化对象时设置访问器不被调用
Set accessor not being called when I deserialise object from Json.net
public class SpecialObject
{
public string ID;
[JsonIgnore]
public List<SpecialObject> SpecialObjectCollection = new List<SpecialObject>();
[JsonIgnore]
public List<string> tempObjectIDs = new List<string>();
[JsonProperty]
public List<string> SpecialObjectIDs { get { return SpecialObjectCollection.Select(x => x.ID).ToList(); } set { tempObjectIDs = value; } }
public SpecialObject() { }
public SpecialObject(string _id) { ID = _id; }
}
static void Main(string[] args)
{
SpecialObject parent = new SpecialObject("parentIDstring");
parent.SpecialObjectCollection.Add(new SpecialObject("childIDstring"));
string test = JsonConvert.SerializeObject(parent);
SpecialObject reconstructedObject = JsonConvert.DeserializeObject<SpecialObject>(test);
}
//string test:
//{"ID":"parentIDstring","SpecialObjectIDs":["childIDstring"]}
我想将 SpecialObject 序列化为 JSON 然后再序列化。 "SpecialObjectIDs" 访问器让我避免了讨厌的循环引用并帮助我重建复杂的关系网络,因为我只需要唯一的 ID。
它序列化得很好,但我需要反序列化对象;当我这样做时,我的数组(JSON 中的 SpecialObjectIDs)在转换过程中消失了,set 访问器似乎没有被调用。
如何让 Newtonsoft.Json (JSON.net) 库将反序列化列表放入 tempObjectIDs 但保持现有的获取行为?
你的问题是,当反序列化一个非只读的集合时,Json.NET 检查集合是否已经分配,例如在包含类型的构造函数中。如果是这样,它将为反序列化的 JSON 内容填充预先存在的集合,并且永远不会将集合设置回去。不幸的是,您的 属性 returns 是一个临时代理集合,因此您的容器 class SpecialObject
永远不会收到反序列化的结果。
防止这种情况的最简单方法是通过 JsonPropertyAttribute
setting ObjectCreationHandling = ObjectCreationHandling.Replace
[JsonProperty(ObjectCreationHandling = ObjectCreationHandling.Replace)]
public List<string> SpecialObjectIDs { get { return SpecialObjectCollection.Select(x => x.ID).ToList(); } set { tempObjectIDs = value; } }
或者,您可以使用 string []
而不是 List<string>
作为代理集合 属性:
public string [] SpecialObjectIDs { get { return SpecialObjectCollection.Select(x => x.ID).ToArray(); } set { tempObjectIDs = value == null ? null : value.ToList(); } }
由于数组无法调整大小,Json.NET 总是会在反序列化时分配一个新数组,并在完成后将其重新设置。
public class SpecialObject
{
public string ID;
[JsonIgnore]
public List<SpecialObject> SpecialObjectCollection = new List<SpecialObject>();
[JsonIgnore]
public List<string> tempObjectIDs = new List<string>();
[JsonProperty]
public List<string> SpecialObjectIDs { get { return SpecialObjectCollection.Select(x => x.ID).ToList(); } set { tempObjectIDs = value; } }
public SpecialObject() { }
public SpecialObject(string _id) { ID = _id; }
}
static void Main(string[] args)
{
SpecialObject parent = new SpecialObject("parentIDstring");
parent.SpecialObjectCollection.Add(new SpecialObject("childIDstring"));
string test = JsonConvert.SerializeObject(parent);
SpecialObject reconstructedObject = JsonConvert.DeserializeObject<SpecialObject>(test);
}
//string test:
//{"ID":"parentIDstring","SpecialObjectIDs":["childIDstring"]}
我想将 SpecialObject 序列化为 JSON 然后再序列化。 "SpecialObjectIDs" 访问器让我避免了讨厌的循环引用并帮助我重建复杂的关系网络,因为我只需要唯一的 ID。
它序列化得很好,但我需要反序列化对象;当我这样做时,我的数组(JSON 中的 SpecialObjectIDs)在转换过程中消失了,set 访问器似乎没有被调用。
如何让 Newtonsoft.Json (JSON.net) 库将反序列化列表放入 tempObjectIDs 但保持现有的获取行为?
你的问题是,当反序列化一个非只读的集合时,Json.NET 检查集合是否已经分配,例如在包含类型的构造函数中。如果是这样,它将为反序列化的 JSON 内容填充预先存在的集合,并且永远不会将集合设置回去。不幸的是,您的 属性 returns 是一个临时代理集合,因此您的容器 class SpecialObject
永远不会收到反序列化的结果。
防止这种情况的最简单方法是通过 JsonPropertyAttribute
setting ObjectCreationHandling = ObjectCreationHandling.Replace
[JsonProperty(ObjectCreationHandling = ObjectCreationHandling.Replace)]
public List<string> SpecialObjectIDs { get { return SpecialObjectCollection.Select(x => x.ID).ToList(); } set { tempObjectIDs = value; } }
或者,您可以使用 string []
而不是 List<string>
作为代理集合 属性:
public string [] SpecialObjectIDs { get { return SpecialObjectCollection.Select(x => x.ID).ToArray(); } set { tempObjectIDs = value == null ? null : value.ToList(); } }
由于数组无法调整大小,Json.NET 总是会在反序列化时分配一个新数组,并在完成后将其重新设置。