【问题标题】:How to validate JSON using System.Text.Json before deserialization如何在反序列化之前使用 System.Text.Json 验证 JSON
【发布时间】: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 或为每种类型和一些反序列化验证代码实现自己的转换器卡住了。

标签: json .net-core


【解决方案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);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-24
    • 2021-12-08
    • 2021-05-21
    • 2021-12-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多