CSharp · Console
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Collections.ObjectModel;
using System.Reflection;
using System.Runtime.Serialization;
using System.Data;
using System.ComponentModel;
using System.Globalization;
using System.Collections.Specialized;
using System.Web.Routing;
using System.Net.Mail;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Net;
using System.Runtime.Serialization.Formatters;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
// https://stackoverflow.com/questions/43293914/serialize-listlinkedlistnodeobject-using-json-net
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;
}
}
class TestClass
{
public static void Test()
{
TestFix(new List<LinkedListNode<string>>() { null, null, null });
var l = new LinkedList<string>();
l.AddLast("Kuku");
l.AddLast("Riku");
l.AddLast("Ok");
var lst = new List<LinkedListNode<string>>();
lst.Add(l.First);
lst.Add(l.First.Next);
lst.Add(l.Last);
TestFix(lst);
lst.Add(l.Last);
lst.Add(null);
lst.Add(l.First);
TestFix(lst);
Console.WriteLine("Done.");
}
public static void TestFix(List<LinkedListNode<string>> lst)
{
var settings = new JsonSerializerSettings
{
Converters = { new LinkedListNodeListConverter<string>() },
};
string json = JsonConvert.SerializeObject(lst, Formatting.Indented, settings);
Console.WriteLine("Serialized JSON: ");
Console.WriteLine(json);
var lst2 = JsonConvert.DeserializeObject<List<LinkedListNode<string>>>(json, settings);
var json2 = JsonConvert.SerializeObject(lst2, Formatting.Indented, settings);
Console.WriteLine("Deserialized and re-serialized JSON: ");
Console.WriteLine(json2);
Assert.IsTrue(JToken.DeepEquals(JToken.Parse(json), JToken.Parse(json2)));
Assert.IsTrue(lst.Select(n => n == null ? null : n.Value).SequenceEqual(lst2.Select(n => n == null ? null : n.Value)));
Console.Write("Node list serialied and deserialize successfully.\n");
}
}
public class AssertionFailedException : System.Exception
{
public AssertionFailedException() : base() { }
public AssertionFailedException(string s) : base(s) { }
}
public static class Assert
{
public static void IsTrue(bool value)
{
if (value == false)
throw new AssertionFailedException("failed");
}
}
public class Program
{
public static void Main()
{
Console.WriteLine("Environment version: " + Environment.Version);
Console.WriteLine("Json.NET version: " + typeof(JsonSerializer).Assembly.FullName);
Console.WriteLine("");
TestClass.Test();
}
}