questions/50143793/deserialize-listobject-using-newtonsoft-cannot-convert-ilist#50143793

CSharp · Console

/Program.cs

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization.Formatters;
using System.IO;
using System.Data;
using System.ComponentModel.DataAnnotations;
using System.Globalization;


using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;	

using LeanKit.API.Client.Library.TransferObjects;

// https://stackoverflow.com/questions/50143793/deserialize-listobject-using-newtonsoft-cannot-convert-ilist#50143793

	public class MyCommentList
	{
		public string ReplyText { get; set; }
		
		[JsonProperty(ItemConverterType = typeof(SingleOrArrayConverter<Comment>))]
		public List<List<Comment>> ReplyData { get; set; }
		public string ReplyCode { get; set; }
	} 

#if true
namespace LeanKit.API.Client.Library.TransferObjects
{
	// Taken from 
	// https://github.com/LeanKit/LeanKit.API.Client/blob/master/LeanKit.API.Client.Library/TransferObjects/Comment.cs
	public class Comment
	{
		public long Id { get; set; }

		[Required(ErrorMessage = "Text may not be empty")]
		[StringLength(4000, ErrorMessage = "Text may have 2000 symbols only")]
		public string Text { get; set; }

		public string PostDate { get; set; }
		public string PostedByGravatarLink { get; set; }
		public long PostedById { get; set; }
		public string PostedByFullName { get; set; }
		public bool Editable { get; set; }
	}
}	
#else
	public class Comment
	{
		public int Id { get; set; }
		public string Text { get; set; }
		public object TaggedUsers { get; set; }
		public string PostDate { get; set; }
		public string PostedByGravatarLink { get; set; }
		public int PostedById { get; set; }
		public string PostedByFullName { get; set; }
		public bool Editable { get; set; }
	}
#endif

	class SingleOrArrayConverter<T> : JsonConverter
	{
		public override bool CanConvert(Type objectType)
		{
			return (objectType == typeof(List<T>));
		}
	
		public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
		{
			JToken token = JToken.Load(reader);
			if (token.Type == JTokenType.Array)
			{
				return token.ToObject<List<T>>();
			}
			return new List<T> { token.ToObject<T>() };
		}
	
		public override bool CanWrite
		{
			get { return false; }
		}
	
		public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
		{
			throw new NotImplementedException();
		}
	}					  
					  
    class TestClass
    {
        public static void Test()
        {
			var responseString = GetJson();
			
			var mycomment = JsonConvert.DeserializeObject<MyCommentList>(responseString);
			
			var newJson = JsonConvert.SerializeObject(mycomment, Formatting.Indented);
			
			Console.WriteLine("\nRe-serialized JSON: ");
			Console.WriteLine(newJson);
			
		}
		
		static string GetJson()
		{
			var json = @"{
  ""ReplyData"": [
    [
      {
        ""Id"": 256487698,
        ""Text"": ""First comment for this card."",
        ""TaggedUsers"": null,
        ""PostDate"": ""10/14/2015 at 04:36:02 PM"",
        ""PostedByGravatarLink"": ""3ab1249be442027903e1180025340b3f"",
        ""PostedById"": 62984826,
        ""PostedByFullName"": ""David Neal"",
        ""Editable"": true
      }
    ]
  ],
  ""ReplyCode"": 200,
  ""ReplyText"": ""Card comments successfully retrieved.""
}";
			return json;
		}
	}


	public class Program
	{
		public static void Main()
		{
			Console.WriteLine("Environment version: " + Environment.Version);
			Console.WriteLine("Json.NET version: " + typeof(JsonSerializer).Assembly.FullName);
			Console.WriteLine();

			try
			{
				TestClass.Test();
			}
			catch (Exception ex)
			{
				Console.WriteLine("Failed with unhandled exception: ");
				Console.WriteLine(ex);
				throw;
			}
		}
	}

    public class AssertionFailedException : System.Exception
    {
        public AssertionFailedException() : base() { }

        public AssertionFailedException(string s) : base(s) { }
    }

    public static class Assert
    {
        public static void IsTrue(bool value)
        {
            IsTrue(value, "failed");
        }

        public static void IsTrue(bool value, string message)
        {
            if (value == false)
                throw new AssertionFailedException(message ?? "failed");
        }
    }
;