C# 序列化列表<;LinkedListNode<;对象>&燃气轮机;使用Json.net

C# 序列化列表<;LinkedListNode<;对象>&燃气轮机;使用Json.net,c#,serialization,json.net,C#,Serialization,Json.net,带有字符串的代码示例也引发异常: LinkedList<string> l = new LinkedList<string>(); l.AddLast("Kuku"); l.AddLast("Riku"); l.AddLast("Ok"); List<LinkedListNode<string>> lst = new List<LinkedListNode<string&g

带有字符串的代码示例也引发异常:

LinkedList<string> l = new LinkedList<string>();
        l.AddLast("Kuku");
        l.AddLast("Riku");
        l.AddLast("Ok");
        List<LinkedListNode<string>> lst = new List<LinkedListNode<string>>();
        lst.Add(l.First);
        lst.Add(l.First.Next);
        lst.Add(l.Last);

        string json = JsonConvert.SerializeObject(lst, Formatting.Indented,
       new JsonSerializerSettings
       {
           ReferenceLoopHandling = ReferenceLoopHandling.Serialize
       });
        File.WriteAllText(@"C:\Student Routine\Data.txt", json);`
LinkedList l=新建LinkedList();
l、 AddLast(“Kuku”);
l、 AddLast(“Riku”);
l、 AddLast(“Ok”);
List lst=新列表();
第一条增补(第一条);
第一次添加(第一次添加,第二次添加);
第一次添加(最后一次添加);
string json=JsonConvert.SerializeObject(lst,Formatting.Indented,
新JsonSerializerSettings
{
ReferenceLoopHandling=ReferenceLoopHandling.Serialize
});
writealText(@“C:\Student Routine\Data.txt”,json)`
我无法使用Json.net序列化
列表
,因为存在自引用错误

错误:检测到类型为“System.Collections.Generic.LinkedListNode”“1[Calendar_Module.ScheduleEvent]”的属性“Previous”的自引用循环。路径“[0]。UserData.Calendar.Days.2017-04-02T00:00:00[0]。下一个。下一个。下一个。下一个。下一个。下一个。下一个

请帮忙

Unhandled Exception:
System.Runtime.Serialization.SerializationException: Type System.Collections.Generic.LinkedListNode`1[System.String] is not marked as Serializable.
换句话说,如果要序列化LinkedListNode,请不要使用它。

序列化
列表是一件有点奇怪的事情,通常只需序列化底层的链接列表即可。也许您正在尝试序列化一个表,该表以不同于底层列表的顺序排列节点

如果是这种情况,则可以使用combined with序列化节点列表,但是由于Json.NET的某些限制,这会失败:

  • PreserveReferencesHandling
    不是针对只读属性实现的(请参阅),而是所有只读属性。这会阻止循环依赖项的正确序列化,并最终导致下一个和上一个节点属性的无限递归

  • PreserveReferencesHandling
    不为具有非默认构造函数的对象实现(请参见),但的唯一公共构造函数是参数化的

因此,您需要为节点列表创建一个:

public class LinkedListNodeListConverter<T> : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return typeof(List<LinkedListNode<T>>).IsAssignableFrom(objectType);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null)
            return null;
        var list = (existingValue as IList<LinkedListNode<T>> ?? (IList<LinkedListNode<T>>)serializer.ContractResolver.ResolveContract(objectType).DefaultCreator());
        var table = serializer.Deserialize<LinkedListNodeOrderTable<T>>(reader);
        foreach (var node in table.ToNodeList())
            list.Add(node);
        return list;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var list = (IList<LinkedListNode<T>>)value;
        var table = LinkedListNodeOrderTable<T>.FromList(list);
        serializer.Serialize(writer, table);
    }
}

class LinkedListNodeOrderTable<T>
{
    public static LinkedListNodeOrderTable<T> FromList(IList<LinkedListNode<T>> nodeList)
    {
        if (nodeList == null)
            return null;
        try
        {
            var list = nodeList.Where(n => n != null).Select(n => n.List).Distinct().SingleOrDefault();
            var table = new LinkedListNodeOrderTable<T>(list);
            var dictionary = list == null ? null : list.EnumerateNodes().Select((n, i) => new KeyValuePair<LinkedListNode<T>, int>(n, i)).ToDictionary(p => p.Key, p => p.Value);
            table.Indices = nodeList.Select(n => (n == null ? -1 : dictionary[n])).ToList();
            return table;
        }
        catch (Exception ex)
        {
            throw new JsonSerializationException(string.Format("Failed to construct LinkedListNodeOrderTable<{0}>",  typeof(T)), ex);
        }
    }

    public LinkedListNodeOrderTable(LinkedList<T> List)
    {
        this.List = List;
    }

    public LinkedList<T> List { get; set; }

    public List<int> Indices { get; set; }

    public IEnumerable<LinkedListNode<T>> ToNodeList()
    {
        if (Indices == null || Indices.Count < 1)
            return Enumerable.Empty<LinkedListNode<T>>();
        var array = List == null ? null : List.EnumerateNodes().ToArray();
        return Indices.Select(i => (i == -1 ? null : array[i]));
    }
}

public static class LinkedListExtensions
{
    public static IEnumerable<LinkedListNode<T>> EnumerateNodes<T>(this LinkedList<T> list)
    {
        if (list == null)
            yield break;
        for (var node = list.First; node != null; node = node.Next)
            yield return node;
    }
}
请注意,转换器假定列表中的所有节点都是相同基础
LinkedList
的成员。如果没有,将抛出异常


示例。

这是可能的,但参考文献存在问题。如果您使用BinarryFormatter,则需要可序列化的属性,这非常有帮助
var settings = new JsonSerializerSettings
{
    Converters = { new LinkedListNodeListConverter<string>() },
};
string json = JsonConvert.SerializeObject(lst, Formatting.Indented, settings);
{
  "List": [
    "Kuku",
    "Riku",
    "Ok"
  ],
  "Indices": [
    0,
    1,
    2
  ]
}