一尘不染

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

json

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)库以将反序列化的列表放入tempObjectID中,但保留现有的get行为?


阅读 268

收藏
2020-07-27

共1个答案

一尘不染

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

防止这种情况的最简单方法是,通过JsonPropertyAttribute设置,指定Json.NET应该始终分配一个新集合并将其重新设置,而不是重用先前存在的集合。[`ObjectCreationHandling

ObjectCreationHandling.Replace`](https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_ObjectCreationHandling.htm)

[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将始终在反序列化时分配一个新数组,并在完成后将其重新设置。

2020-07-27