using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
using System.Web.SessionState;
public class MyFirstClass
public int Id { get; set; }
public string Name { get; set; }
public List<MySecondClass> Roles { get; set; }
public class MySecondClass
public List<MyThirdClass> Roles { get; set; }
public class MyThirdClass
public int RoleId { get; set; }
public string RoleName { get; set; }
public sealed class MyThirdClassStringConverter : JsonConverter
readonly JsonSerializerSettings settings;
public MyThirdClassStringConverter() : this(null) { }
public MyThirdClassStringConverter(JsonSerializerSettings settings)
this.settings = settings;
JsonSerializer GetInnerSerializer()
var innerSerializer = JsonSerializer.CreateDefault(settings);
for (int i = innerSerializer.Converters.Count - 1; i >= 0; i--)
if (innerSerializer.Converters[i] is MyThirdClassStringConverter)
innerSerializer.Converters.RemoveAt(i);
public override bool CanConvert(Type objectType)
return typeof(MyThirdClass).IsAssignableFrom(objectType);
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
if (reader.TokenType == JsonToken.Null)
var innerSerializer = GetInnerSerializer();
if (reader.TokenType == JsonToken.String)
var s = reader.Value.ToString();
using (var innerReader = new StringReader(s))
return innerSerializer.Deserialize(innerReader, objectType);
return innerSerializer.Deserialize(reader, objectType);
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
var innerSerializer = GetInnerSerializer();
var sb = new StringBuilder();
using (var innerWriter = new StringWriter(sb))
innerSerializer.Serialize(innerWriter, value);
writer.WriteValue(sb.ToString());
""{\""RoleId\"":123,\""RoleName\"":\""123\""}"",
""{\""RoleId\"":234,\""RoleName\"":\""234\""}""
""{\""RoleId\"":123,\""RoleName\"":\""123\""}"",
""{\""RoleId\"":234,\""RoleName\"":\""234\""}""
public static void Test()
var stringJson = GetJson();
Console.WriteLine("Original JSON: ");
Console.WriteLine(stringJson);
var stringSettings = new JsonSerializerSettings { Converters = new[] { new MyThirdClassStringConverter() } };
var root = JsonConvert.DeserializeObject<MyFirstClass>(stringJson, stringSettings);
var newNonStringJson = JsonConvert.SerializeObject(root, Formatting.Indented);
var newStringJson = JsonConvert.SerializeObject(root, Formatting.Indented, stringSettings);
Console.WriteLine("Re-serialized JSON with MyThirdClass serialized as objects: ");
Console.WriteLine(newNonStringJson);
Console.WriteLine("Re-serialized JSON with MyThirdClass serialized as strings: ");
Console.WriteLine(newStringJson);
if (!JToken.DeepEquals(JToken.Parse(stringJson), JToken.Parse(newStringJson)))
throw new InvalidOperationException("JToken.DeepEquals(JToken.Parse(stringJson), JToken.Parse(newStringJson))");
Console.WriteLine("Original and re-serialized JSON with MyThirdClass converted to strings are identical.");
if (!JToken.DeepEquals(JToken.FromObject(root), JToken.FromObject(JsonConvert.DeserializeObject<MyFirstClass>(newNonStringJson, stringSettings))))
throw new InvalidOperationException("Deserializing JSON with objects using MyThirdClassStringConverter failed");
Console.WriteLine("Deserializing JSON with objects using MyThirdClassStringConverter succeeded");
public static void Main()