如何在反序列化之前使用 System.Text.Json 验证 JSON

Posted

技术标签:

【中文标题】如何在反序列化之前使用 System.Text.Json 验证 JSON【英文标题】:How to validate JSON using System.Text.Json before deserialization 【发布时间】:2021-07-15 19:27:27 【问题描述】:

在 .NET Core 5.0 中,使用 System.Text.Json.JsonSerializer Deserialize(someJsonFile) 我得到:

System.Text.Json.JsonException: 'The JSON value could not be converted to System.Guid. Path: $.someGuid | ..

这是预期的,因为 someGuid 属性是 System.Guid 类型,并且 JSON 文件/字符串中 someGuid 的值是:


  "someGuid": ""

无法正确反序列化..(因为它不是 Guid.Empty)..

我的问题。

在反序列化之前验证 Json(通常)有什么好的和通用的实现?像 TryParse 或 JsonDocument.Parse?当然,try-catch 但这很脏(恕我直言)。

顺便说一句:我不想使用 Newtonsoft

感谢您的建议(当然还有批评者)。

【问题讨论】:

好像在road-map。有可用的第 3 方解决方案。 我认为你被 try/catch 或为每种类型和一些反序列化验证代码实现自己的转换器卡住了。 【参考方案1】:

我使用示例创建了一个自定义转换器,答案是:The JSON value could not be converted to System.Int32

public class StringToGuidConverter : JsonConverter<Guid>
    
        public override Guid Read(ref Utf8JsonReader reader, Type type, JsonSerializerOptions options)
        
            if (reader.TokenType == JsonTokenType.String)
            
                ReadOnlySpan<byte> span = reader.ValueSpan;
                if (Utf8Parser.TryParse(span, out Guid guid, out int bytesConsumed) && span.Length == bytesConsumed)
                
                    return guid;
                

                if (Guid.TryParse(reader.GetString(), out guid))
                
                    return guid;
                
            

            return Guid.Empty;
        

        public override void Write(Utf8JsonWriter writer, Guid value, JsonSerializerOptions options)
        
            writer.WriteStringValue(value.ToString());
        
    

在我的例子中,我的模型要反序列化为不能采用 Nullable Guid,所以我返回一个空的 GUID,然后在我的逻辑中验证它。

因为我使用 .Net 标准创建了一个 web api,所以我无法在启动类的服务中注册它。但是您可以在调用 Deserialize 方法时使用 JsonSerializerOptions 属性注册自定义转换器,如下所示:

var options = new JsonSerializerOptions

    PropertyNameCaseInsensitive = true,
    Converters =  new NERDS.API.Helpers.StringToGuidConverter() 
;

StreamReader reader = new StreamReader(HttpContext.Current.Request.InputStream);
string json = reader.ReadToEnd();
return JsonSerializer.Deserialize<T>(json, options);

【讨论】:

以上是关于如何在反序列化之前使用 System.Text.Json 验证 JSON的主要内容,如果未能解决你的问题,请参考以下文章

在反序列化时如何忽略JSON对象数组中的空白数组?

Protobuf-net r282 在反序列化使用 r249 序列化的对象时遇到问题

在 xml 序列化期间忽略属性,但在反序列化期间不忽略

在反序列化过程中出现下一个异常:“源数据中的无效字段:0”。如何找出源代码中的原因/错误位置?

在反序列化期间使用 XML 装饰指定默认值

在反序列化时使用动态和强制执行 WCF 合同