Using System.Text.Json
, I am writing a custom JsonConverter<T>.Read()
deserialization method to deserialize a JSON object. The method reads each property name and value from the JSON and manually assigns the results into the deserialized object, along the lines of the example shown in the Microsoft documentation How to write custom converters for JSON serialization (marshalling) in .NET: Support polymorphic deserialization. However, in my case the JSON object will sometimes contain unknown properties that I want to simply ignore. When this happens, the example code in the documentation will cause an exception to be thrown:
JsonException: The converter 'PersonConverter' read too much or not enough.
How can I correctly skip past unknown properties in a custom object deserializer?
A minimal example follows. Say I have the following data model:
public class Person
{
public string Name { get; set; }
}
And the following converter:
public class PersonConverter : JsonConverter<Person>
{
public override bool CanConvert(Type typeToConvert) =>
typeof(Person).IsAssignableFrom(typeToConvert);
public override Person Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.Null)
return null;
if (reader.TokenType != JsonTokenType.StartObject)
throw new JsonException();
var person = new Person();
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.EndObject)
return person;
if (reader.TokenType == JsonTokenType.PropertyName)
{
var propertyName = reader.GetString();
reader.Read();
switch (propertyName)
{
case "Name":
person.Name = reader.GetString();
break;
}
}
}
throw new JsonException();
}
public override void Write(Utf8JsonWriter writer, Person person, JsonSerializerOptions options) => throw new NotImplementedException();
}
When attempting to deserialize the following JSON:
{"Name":"my name", "ExtraData" : {"Value" : "extra value"} }
Via:
var json = @"{""Name"":""my name"", ""ExtraData"" : {""Value"" : ""extra value""} }";
var options = new JsonSerializerOptions
{
Converters = { new PersonConverter() },
};
var person = JsonSerializer.Deserialize<Person>(json, options);
The following exception is thrown:
System.Text.Json.JsonException: The converter 'PersonConverter' read too much or not enough. Path: $ | LineNumber: 0 | BytePositionInLine: 58. at System.Text.Json.ThrowHelper.ThrowJsonException_SerializationConverterRead(JsonConverter converter) at System.Text.Json.Serialization.JsonConverter`1.VerifyRead(JsonTokenType tokenType, Int32 depth, Int64 bytesConsumed, Boolean isValueConverter, Utf8JsonReader& reader) at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value) at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state) at System.Text.Json.JsonSerializer.ReadCore[TValue](JsonConverter jsonConverter, Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state) at System.Text.Json.JsonSerializer.ReadCore[TValue](Utf8JsonReader& reader, Type returnType, JsonSerializerOptions options) at System.Text.Json.JsonSerializer.Deserialize[TValue](String json, Type returnType, JsonSerializerOptions options) at System.Text.Json.JsonSerializer.Deserialize[TValue](String json, JsonSerializerOptions options)
How can I correct the logic of the converter to avoid this exception?
A simplified demo fiddle is here: fiddle #1.
A demo of the converter from the documentation throwing the same exception is here: fiddle #2.