How to force System.Text.Json serializer throw exception when property is missing?

瘦欲@ 提交于 2021-01-27 07:16:57

问题


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

  1. Use Json.NET
  2. Validate the objects after serialisation with the Validator class
  3. 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!