Reputation: 13983
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?
Upvotes: 17
Views: 12302
Reputation: 10527
In System.Text.Json
you can set RespectRequiredConstructorParameters
property on the JsonSerializerOptions
to true
. With that, trying to deserialize "{}"
for:
record Foo(string Text);
will throw a JsonException
:
JSON deserialization for type 'Foo' was missing required properties including: 'Text'.
Upvotes: 0
Reputation: 2973
Pass in an implementation of DefaultJsonTypeInfoResolver
, which marks every property as required.
using System.Text.Json;
var options = new JsonSerializerOptions {
TypeInfoResolver = new DefaultJsonTypeInfoResolver {
Modifiers = {
typeInfo => {
foreach (JsonPropertyInfo property in typeInfo.Properties) {
property.IsRequired = true;
}
}
}
}
};
return JsonSerializer.Deserialize<T>(content, options);
Upvotes: 0
Reputation: 781
The [JsonRequired]
attribute from System.Text.Json
works as requested, but it is available starting with .NET 7. See Required properties documentation.
In addition, in .NET 8 you can also force the JSON string to properly map to POCO/model properties using JsonUnmappedMemberHandling.Disallow
option. See Handle missing members during deserialization documentation.
Upvotes: 5
Reputation: 19
All you need to do SetMissingMemberHandling and it will handle every thing for you but you need to install DevBetter.JsonExtensions MissingMemberHandling.Ignore and MissingMemberHandling.Error
var deserializeOptions = new JsonSerializerOptions()
.SetMissingMemberHandling(MissingMemberHandling.Ignore);
var weatherForecast = JsonSerializer.Deserialize<WeatherForecast>(jsonString, deserializeOptions);
Upvotes: 1
Reputation: 131364
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
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
}
Upvotes: 5
Reputation: 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.
Upvotes: 5