Czy według Was warto opakować metodę Read
z poniższego kodu, try catchem wyłapującym InvalidCastException
, a następnie rzucającym JsonException
? Czy może napisać tę metodę tak, żeby nie doszło do takiej sytuacji i od razu rzucać JsonException
.
Kod pochodzi z dokumentacji.
Przykładowy json, który powoduje InvalidCastException:
{
"TypeDiscriminator": 1,
"OfficeNumber": 13
}
namespace SystemTextJsonSamples
{
public class PersonConverterWithTypeDiscriminator : JsonConverter<Person>
{
enum TypeDiscriminator
{
Customer = 1,
Employee = 2
}
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.StartObject)
{
throw new JsonException();
}
reader.Read();
if (reader.TokenType != JsonTokenType.PropertyName)
{
throw new JsonException();
}
string propertyName = reader.GetString();
if (propertyName != "TypeDiscriminator")
{
throw new JsonException();
}
reader.Read();
if (reader.TokenType != JsonTokenType.Number)
{
throw new JsonException();
}
TypeDiscriminator typeDiscriminator = (TypeDiscriminator)reader.GetInt32();
Person person = typeDiscriminator switch
{
TypeDiscriminator.Customer => new Customer(),
TypeDiscriminator.Employee => new Employee(),
_ => throw new JsonException()
};
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.EndObject)
{
return person;
}
if (reader.TokenType == JsonTokenType.PropertyName)
{
propertyName = reader.GetString();
reader.Read();
switch (propertyName)
{
case "CreditLimit":
decimal creditLimit = reader.GetDecimal();
((Customer)person).CreditLimit = creditLimit;
break;
case "OfficeNumber":
string officeNumber = reader.GetString();
((Employee)person).OfficeNumber = officeNumber;
break;
case "Name":
string name = reader.GetString();
person.Name = name;
break;
}
}
}
throw new JsonException();
}
//...
}
}