设置从 Json.net 反序列化对象时不调用的访问器

本文关键字:调用 访问 对象 Json net 反序列化 设置 | 更新日期: 2023-09-27 18:21:07

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"]}

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

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

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

设置从 Json.net 反序列化对象时不调用的访问器

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

防止这种情况的最简单方法是指定 Json.NET 应始终分配新集合并将其设置回来,而不是通过JsonPropertyAttribute设置重用预先存在的集合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 在反序列化时将始终分配一个新数组,并在完成后将其重新设置。