title: Handling null objects in custom JsonConverter's ReadJson method
body: <p>I've got a Newtonsoft JSON.NET <code>JsonConverter</code> to help deserialize a property whose type is an abstract class. The gist of it looks like this:</p>
  
  <pre><code>public class PetConverter : JsonConverter
  {
      public override bool CanConvert(Type objectType)
      {
          return objectType == typeof(Animal);
      }
  
      public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
      {
          JObject jsonObject = JObject.Load(reader);
  
          if (jsonObject["Lives"] != null) return jsonObject.ToObject&lt;Cat&gt;(serializer);
          if (jsonObject["StopPhrase"] != null) return jsonObject.ToObject&lt;Parrot&gt;(serializer);
  
          return null;
      }
  
      public override bool CanWrite { get { return false; } }
  
      public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
      { throw new NotImplementedException(); }
  }
  </code></pre>
  
  <p>Here are the classes it handles:</p>
  
  <pre><code>public abstract class Animal 
  { }
  
  public class Cat : Animal
  {
      public int Lives { get; set; }
  }
  
  public class Parrot : Animal
  {
      public string StopPhrase { get; set; }
  }
  
  public class Person
  {
      [JsonConverter(typeof(PetConverter))]
      public Animal Pet { get; set; }
  }
  </code></pre>
  
  <p>This works fine when deserializing a <code>Person</code> that has a non-null <code>Pet</code>. But if the <code>Pet</code> is null, then the <code>ReadJson</code> method breaks on the first line with this a <code>JsonReaderException</code>:</p>
  
  <blockquote>
    <p>An exception of type 'Newtonsoft.Json.JsonReaderException' occurred in Newtonsoft.Json.dll but was not handled in user code</p>
    
    <p>Additional information: Error reading JObject from JsonReader. Current JsonReader item is not an object: Null. Path 'Pet', line 1, position 11.</p>
  </blockquote>
  
  <p>I've checked <a href="http://www.newtonsoft.com/json/help/html/CustomJsonConverter.htm" rel="noreferrer">the Custom JsonConverter</a> documentation, but it is merely about a <em>writing</em> converter. I've tried the following:</p>
  
  <pre><code>if (reader.Value == null) return null; // this inverts the [Test] results
  </code></pre>
  
  <p>But then I get:</p>
  
  <blockquote>
    <p>JsonSerializationException: Additional text found in JSON string after finishing deserializing object.</p>
  </blockquote>
  
  <p>For cases when the property <em>is</em> populated.</p>
  
  <p>In short, what is the proper way to handle this situation?</p>
  
  <hr>
  
  <p>For completeness, here are some unit tests that demonstrate the issue at hand:</p>
  
  <pre><code>[TestFixture]
  public class JsonConverterTests
  {
      [Test]
      public void Cat_survives_serialization_roundtrip()
      {
          var person = new Person { Pet = new Cat { Lives = 9 } };
          var serialized = JsonConvert.SerializeObject(person);
          var deserialized = JsonConvert.DeserializeObject&lt;Person&gt;(serialized);
          Assert.That(deserialized.Pet, Is.InstanceOf&lt;Cat&gt;());
          Assert.That((deserialized.Pet as Cat).Lives, Is.EqualTo(9));
      }
  
      [Test]
      public void Parrot_survives_serialization_roundtrip()
      {
          var person = new Person { Pet = new Parrot { StopPhrase = "Lorrie!" } };
          var serialized = JsonConvert.SerializeObject(person);
          var deserialized = JsonConvert.DeserializeObject&lt;Person&gt;(serialized);
          Assert.That(deserialized.Pet, Is.InstanceOf&lt;Parrot&gt;());
          Assert.That((deserialized.Pet as Parrot).StopPhrase, Is.EqualTo("Lorrie!"));
      }
  
      [Test]
      public void Null_property_does_not_break_converter()
      {
          var person = new Person { Pet = null };
          var serialized = JsonConvert.SerializeObject(person);
          var deserialized = JsonConvert.DeserializeObject&lt;Person&gt;(serialized);
          Assert.That(deserialized.Pet, Is.Null);
      }
  }
  </code></pre>