2017-04-08 87 views
-6

与串的代码示例也抛出异常:序列化列表<一个LinkedListNode <object>>使用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>>(); 
     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);` 

我不能序列​​由于自我引荐误差,使用Json.net。

错误:为属性'Previous'检测到自回参考循环,类型为'System.Collections.Generic.LinkedListNode`1 [Calendar_Module.ScheduleEvent]'。路径'[0] .UserData.Calendar.Days.2017-04-02T00:00:00 [0] .Next.Next.Next.Next.Next.Next'。

请帮助

+1

你究竟想在这里完成什么? –

回答

2

序列化List<LinkedListNode<string>>是有点的一个奇怪的事情要做 - 通常一个只想序列化底层链表。也许你试图序列化一个表,该表给出了与底层列表不同的顺序?

如果是这样的话,它可能会出现,人们可以使用序列化与PreserveReferencesHandling.All联合ReferenceLoopHandling.Serialize节点列表,但是这个失败,因为Json.NET的一些限制:

  • PreserveReferencesHandling不读执行 - 仅属性(请参阅here),但LinkedListNode.List,.Next.Previous均为只读属性。这会阻止循环依赖的正确序列化,并最终导致对下一个和前一个节点属性的无限递归。

  • PreserveReferencesHandling未针对具有非默认构造函数的对象实现(请参见here),但LinkedListNode<T>的唯一公共构造方法已参数化。

因此,您需要为您的节点列表中custom JsonConverter

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; 
    } 
} 

,并使用以下设置:

var settings = new JsonSerializerSettings 
{ 
    Converters = { new LinkedListNodeListConverter<string>() }, 
}; 
string json = JsonConvert.SerializeObject(lst, Formatting.Indented, settings); 

产生的JSON的样子:

{ 
    "List": [ 
    "Kuku", 
    "Riku", 
    "Ok" 
    ], 
    "Indices": [ 
    0, 
    1, 
    2 
    ] 
} 

请注意,转换器假定列表中的所有节点都是相同底层LinkedList<T>的成员。如果不会抛出异常。

样品fiddle

+0

非常感谢你,非常有帮助 –

0
Unhandled Exception: 
System.Runtime.Serialization.SerializationException: Type System.Collections.Generic.LinkedListNode`1[System.String] is not marked as Serializable. 

换句话说,如果你打算把它序列化不使用一个LinkedListNode ...

+0

这是可能的,但是引用存在问题。如果你使用BinarryFormatter,你需要Serializable属性 –

相关问题