问题
Json.NET behaviour could be defined by attributes: either use default or just throw an exception if json payload does not contain required property.
Yet System.Text.Json
serializer silently does nothing.
Having class:
public sealed class Foo
{
[Required]
public int Prop {get;set;} = 10;
}
and deserializing empty object:
JsonSerializer.Deserialize<Foo>("{}");
I simply get an instance of Foo
with Prop=10
.
I could not find any setting in JsonSerializerOptions to force it throw an exception. Is it possible?
回答1:
System.Text.Json doesn't throw an exception if no value is received for one of the properties of the target type. You need to implement a custom converter.
Reference: https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-migrate-from-newtonsoft-how-to#required-properties
回答2:
As others have mentioned you could write a converter, here is an example of how you might go about that
public class ThrowOnNull<T> : JsonConverter<T>
{
public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.Null)
{
throw new SomeFunkyExeption();
}
return JsonSerializer.Deserialize<T>(ref reader);
}
public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
{
JsonSerializer.Serialize(writer,value);
}
}
[JsonConverter(typeof(ThrowOnNull<int>))]
public int SomeValue{ get; set; }
回答3:
System.Text.Json isn't a full replacement for Json.NET. It's built for speed with minimal allocations in mind, not feature completeness. If you want validations you can
- Use Json.NET
- Validate the objects after serialisation with the Validator class
- Create a custom converter
TheGeneral showed how to do #3. A custom validator would have to handle all validations explicitly and return some meaningful exception though. Throwing an ArgumentNullException
is enough if there's only a single property to check. Validating multiple properties would require something more complex like a ValidationException to include the validation results.
K. Scott Allen's article Manual Validation with Data Annotations shows how to do #2.
One option is to use the Validator.ValidateObject to validate an object and get a ValidationException
with all the failing validations :
try
{
var validationCtx=new ValidationContexgt(myFoo);
Validator.ValidateObject(myFoo,validationCtx);
}
catch(ValidatinException ex)
{
//Do something with the results.
}
This is OK if invalid objects are rare, as throwing exceptions is expensive. Perhaps a better option is to use Validator.TryValidateObject :
var results = new List<ValidationResult>();
var validationCtx=new ValidationContexgt(myFoo);
if(Validator.TryValidateObject(myFoo,validationCtx,results))
{
//Use the object
}
else
{
//Do something with the failed results
}
来源:https://stackoverflow.com/questions/62570159/how-to-force-system-text-json-serializer-throw-exception-when-property-is-missin