title: StackOverflowException when deserializing a hierarchy of immutable polymorphic types with Newtonsoft JSON
body: <p>I have a hierarchy of polymorphic immutable classes that I would like to serialize to and deserialize from JSON using Newtonsoft JSON.</p>
  
  <p>Here's a simplified set of example classes:</p>
  
  <pre><code>[JsonConverter(typeof(ItemJsonConveter))]
  public abstract class Item
  {
      [JsonConstructor]
      public Item(string itemType, IList&lt;Item&gt; subItems)
      {
          ItemType = itemType;
          SubItems = subItems ?? new List&lt;Item&gt;();
      }
  
      public string ItemType { get; }
  
      public IList&lt;Item&gt; SubItems { get; }
  }
  
  
  public class Foo : Item
  {
      public const string TypeName = "foo";
  
      [JsonConstructor]
      public Foo(string fooProperty, IList&lt;Item&gt; subItems = null) : base(TypeName, subItems)
      {
          FooProperty = fooProperty;
      }
  
      public string FooProperty { get; }
  }
  
  public class Bar : Item
  {
      public const string TypeName = "bar";
  
      public Bar(string barProperty, IList&lt;Item&gt; subItems = null) : base(TypeName, subItems)
      {
          BarProperty = barProperty;
      }
  
      public string BarProperty { get; }
  }
  </code></pre>
  
  <p>I need the resulting JSON follow a specific format which does not identify types by full class names or using a $type parameter as would happen with other values of <code>TypeNameHandling</code></p>
  
  <p>So I created the following <code>ItemJsonConverter</code> class to read my custom "ItemType" property from the JSON to determine the correct type to deserialize to.</p>
  
  <pre><code>internal class ItemJsonConveter : JsonConverter
  {
      public override bool CanWrite =&gt; false;
  
      public override bool CanConvert(Type objectType)
      {
          if (typeof(Item).IsAssignableFrom(objectType)) return true;
          else return false;
      }
  
      public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
      {
          JObject jo = JObject.Load(reader);
          string typeValue = jo[nameof(Item.ItemType)].Value&lt;string&gt;();
  
          switch (typeValue)
          {
              case Foo.TypeName:
                  return jo.ToObject&lt;Foo&gt;();
  
              case Bar.TypeName:
                  return jo.ToObject&lt;Bar&gt;();
  
              default:
                  throw new InvalidOperationException("Unxpected item type: " + typeValue);
          }
      }
  
      public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
      {
          throw new NotImplementedException();
      }
  }
  </code></pre>
  
  <p>Here's the JSON that is created</p>
  
  <pre><code>{
    "FooProperty": "Foo 1",
    "ItemType": "foo",
    "SubItems": [
      {
        "BarProperty": "Bar 2",
        "ItemType": "bar",
        "SubItems": [
          {
            "FooProperty": "Foo 3",
            "ItemType": "foo",
            "SubItems": []
          },
          {
            "BarProperty": "Bar 3",
            "ItemType": "bar",
            "SubItems": []
          }
        ]
      },
      {
        "FooProperty": "Foo 2",
        "ItemType": "foo",
        "SubItems": []
      }
    ]
  }
  </code></pre>
  
  <p>Yet when I run the following code to test this a <code>StackOverFlowException</code> is thrown in <code>ItemJsonConverter.ReadJson()</code></p>
  
  <pre><code>//Create Model
  Foo foo3 = new Foo("Foo 3");
  Bar bar3 = new Bar("Bar 3");
  Foo foo2 = new Foo("Foo 2");
  Bar bar2 = new Bar("Bar 2", new List&lt;Item&gt;() { foo3, bar3 });
  Foo foo1 = new Foo("Foo 1", new List&lt;Item&gt;() { bar2, foo2 });
  
  //Create serializer
  var ser = new Newtonsoft.Json.JsonSerializer
  {
      Formatting = Newtonsoft.Json.Formatting.Indented,
      TypeNameHandling = Newtonsoft.Json.TypeNameHandling.None,
  };
  
  //Serialize modelt to string
  var tw = new StringWriter();
  ser.Serialize(tw, foo1);
  var stringvalue = tw.ToString();
  
  //Deserialize
  try
  {
      using (var sr = new StringReader(stringvalue))
      {
          using (var jr = new JsonTextReader(sr))
          {
              //This throws StackOverflowException ItemJsonConveter.ReadJson()
              var deserialziedFoo = ser.Deserialize&lt;Foo&gt;(jr);
          }
      }
  }
  catch (System.Exception exp)
  {
      throw;
  }
  </code></pre>
  
  <p>I've read other similar questions about the same issue and the solution has been to replace the calls to <code>JObject.ToObject&lt;T&gt;()</code> with explicit construction of new objects and then use <code>JsonConvert.PopulateObject&lt;t&gt;()</code> to update the objects with the values from the JSON. </p>
  
  <p>However, I would prefer these objects to be completely immutable and for there to be no way for them to be changed after being constructed. (Unless this is the only way to get this to work.)</p>
  
  <p>I was able to get this to work by manually reading values from the <code>JObject</code> in <code>ReadJson()</code> and calling <code>Foo</code> and <code>Bar</code> constructors directly. However, for more complex objects I'd really like to take advantage of Newtonsoft's ability to automagically serialize/derserialize through attributes and reflection and not have to update my serialization code every time a class changes.</p>
  
  <p>Here's the complete sample code as a Gist:
  <a href="https://gist.github.com/aireq/51e4527886ddb076ee8c981264b439a7" rel="nofollow noreferrer">https://gist.github.com/aireq/51e4527886ddb076ee8c981264b439a7</a></p>