https://stackoverflow.com/questions/57303628/newtonsoft-json-error-deserialize-empty-dictionary

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 System.Reflection;

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

using NUnit.Framework; // Throws NUnit.Framework.AssertionException

//https://stackoverflow.com/questions/57303628/newtonsoft-json-error-deserialize-empty-dictionary

	public partial class Welcome
	{
		[JsonConverter(typeof(JsonSingleOrEmptyArrayConverter<Dictionary<long, Result[]>>))]
		public Dictionary<long, Result[]> Results { get; set; }
	}

	public partial class Result
	{
		public long Id { get; set; }
		public string Name { get; set; }
	}

    class TestClass
    {
        public static void Test()
        {
			foreach (var json in GetJson())
			{
				var root = JsonConvert.DeserializeObject<Welcome>(json);
				
				Console.WriteLine(JsonConvert.SerializeObject(root, Formatting.Indented));
			}
		}	
		
		static IEnumerable<string> GetJson()
		{
			var json = new [] { @"{""results"": {
        ""231412354"": [
            {
              ""id"": ""11913258"",
              ""name"" : ""dsa""
            }
        ],
        ""546547654"": [
            {
              ""id"": ""11913258"",
              ""name"" : ""dsa""
            },
        ],
}}",
							   @"{ ""results"": [] }"
							  };
			return json;
		}
	}

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

		public override bool CanWrite { get { return false; } }

		public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
		{
			var contract = serializer.ContractResolver.ResolveContract(objectType);
			if (!(contract is Newtonsoft.Json.Serialization.JsonObjectContract || contract is Newtonsoft.Json.Serialization.JsonDictionaryContract))
			{
				throw new JsonSerializationException(string.Format("Unsupported objectType {0} at {1}.", objectType, reader.Path));
			}

			switch (reader.SkipComments().TokenType)
			{
				case JsonToken.StartArray:
					{
						int count = 0;
						while (reader.Read())
						{
							switch (reader.TokenType)
							{
								case JsonToken.Comment:
									break;
								case JsonToken.EndArray:
									return existingValue;
								default:
									{
										count++;
										if (count > 1)
											throw new JsonSerializationException(string.Format("Too many objects at path {0}.", reader.Path));
										existingValue = existingValue ?? contract.DefaultCreator();
										serializer.Populate(reader, existingValue);
									}
									break;
							}
						}
						// Should not come here.
						throw new JsonSerializationException(string.Format("Unclosed array at path {0}.", reader.Path));
					}

				case JsonToken.Null:
					return null;

				case JsonToken.StartObject:
					existingValue = existingValue ?? contract.DefaultCreator();
					serializer.Populate(reader, existingValue);
					return existingValue;

				default:
					throw new InvalidOperationException("Unexpected token type " + reader.TokenType.ToString());
			}
		}

		public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
		{
			throw new NotImplementedException();
		}
	}

	public static partial class JsonExtensions
	{
		public static JsonReader SkipComments(this JsonReader reader)
		{
			while (reader.TokenType == JsonToken.Comment && reader.Read())
				;
			return reader;
		}
	}

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