当我从Json.net反序列化对象时,设置访问器未被调用

public class SpecialObject { public string ID; [JsonIgnore] public List SpecialObjectCollection = new List(); [JsonIgnore] public List tempObjectIDs = new List(); [JsonProperty] public List 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(test); } //string test: //{"ID":"parentIDstring","SpecialObjectIDs":["childIDstring"]} 

我想将SpecialObject序列化为JSON并再次返回。 “SpecialObjectIDs”访问器让我避免讨厌的循环引用,并帮助我重建复杂的关系网络,因为我只需要唯一的ID。

它序列化很好,但我需要反序列化对象; 当我这样做时,我的数组(JSON中的SpecialObjectIDs)在转换过程中消失了,似乎没有调用set访问器。

如何让Newtonsoft.Json(JSON.net)库将反序列化的List放在tempObjectIDs中,但保留现有的get行为?

您的问题是,在反序列化非只读集合时,Json.NET会检查集合是否已经分配,​​例如在包含类型的构造函数中。 如果是这样,它将填充反序列化的JSON内容的预先存在的集合,并且永远不会将集合设置回来。 不幸的是,您的属性返回一个临时代理集合,因此您的容器类SpecialObject永远不会收到反序列化的结果。

防止这种情况的最简单方法是指定Json.NET应始终分配新集合并将其设置回来,而不是通过JsonPropertyAttribute设置重用预先存在的集合ObjectCreationHandling = ObjectCreationHandling.Replace

 [JsonProperty(ObjectCreationHandling = ObjectCreationHandling.Replace)] public List SpecialObjectIDs { get { return SpecialObjectCollection.Select(x => x.ID).ToList(); } set { tempObjectIDs = value; } } 

或者,您可以为代理集合属性使用string []而不是List

 public string [] SpecialObjectIDs { get { return SpecialObjectCollection.Select(x => x.ID).ToArray(); } set { tempObjectIDs = value == null ? null : value.ToList(); } } 

由于数组无法resize,Json.NET将在反序列化时始终分配一个新数组,并在完成时将其设置回来。