繁体   English   中英

从 Newtonsoft.Json 转移到 System.Text.Json 和 Guid 问题

[英]Move from Newtonsoft.Json to System.Text.Json and Guid problem

我有一个 .NET 5 ASP REST 服务,我正在尝试使用 System.Text 删除 Newtonsoft。
问题是,使用 Newtonsoft,我能够发送没有破折号的 GUID,并且模型已成功绑定,现在我得到空值(使用 System.Text.Json)

我能够使用https://dotnetfiddle.net/ocayBp隔离问题

using System;

public class Program
{
    public static void Main()
    {
        //this works
        var json = "{\"AuthorId\":\"6917d697-c1ab-4fb7-b297-8b2a23100bfc\",\"Title\":\"test title\"}";
        //this doesn't work
        //var json = "{\"AuthorId\":\"6917d697c1ab4fb7b2978b2a23100bfc\",\"Title\":\"test title\"}";
        var result1 = Newtonsoft.Json.JsonConvert.DeserializeObject<Post>(json);
        result1.Dump();
        var result2 = System.Text.Json.JsonSerializer.Deserialize<Post>(json);
        result2.Dump();
    }
}

public class Post
{
    public Guid AuthorId { get; set; }

    public string Title { get; set; }
}

Newtonsoft 正确地将字符串反序列化为 GUID,使用 System.Text.Json 方法我收到此错误:

未处理的异常。 System.Text.Json.JsonException:无法将 JSON 值转换为 System.Guid。 路径:$.AuthorId | 行号:0 | BytePositionInLine:46。---> System.FormatException:JSON 值不是受支持的 Guid 格式。 在 System.Text.Json.Utf8JsonReader.GetGuid() 在 System.Text.Json.Serialization.Converters.GuidConverter.Read(Utf8JsonReader& 阅读器,键入 typeToConvert,JsonSerializerOptions 选项) 在 System.Text.Json.Serialization.Metadata.JsonPropertyInfo 1.ReadJsonAndSetMember(Object obj, ReadStack& state, Utf8JsonReader& reader) at System.Text.Json.Serialization.Converters.ObjectDefaultConverter 1.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value) at System.Text.Json.Serialization .JsonConverter 1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value) at System.Text.Json.Serialization.JsonConverter 1.ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state) --- 内部结束异常堆栈跟踪---在 System.Text.Json.Serialization.JsonConverter 1.ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state) at System.Text.Json.JsonSerializer.ReadFromSpan[TValue](ReadOnlySpan的 System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& state, Utf8JsonReader& reader, Exception ex) 1.ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state) at System.Text.Json.JsonSerializer.ReadFromSpan[TValue](ReadOnlySpan 1 utf8Json, JsonTypeInfo jsonTypeInfo, Nullable 1 actualByteCount) at System.Text.Json.JsonSerializer.ReadFromSpan[TValue](ReadOnlySpan 1 json, JsonTypeInfo jsonTypeInfo) 在 System.Text.Json.JsonSerializer.Deserialize[TValue](String json, JsonSerializerOptions options) 在 Program.Main()

我在ConfigureServices中设置 JSON:

services.AddControllers(
    options =>
    {
        options.ValueProviderFactories.Add(new ClaimValueProviderFactory());
    }).AddJsonOptions(options =>
{
    options.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
    options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
});

如何使用System.Text.Json获得与Newtonsoft.Json相同的行为。

我在 GitHub ( https://github.com/dotnet/runtime/issues/30692 ) 上发现了一个问题,但是没有可以指定格式的TryGetGuid方法。

我们可以尝试通过JsonConverter<T>Guid编写一个客户 JsonConverter

public class GuidJsonConverter: JsonConverter<Guid>
{
    public override Guid Read(
            ref Utf8JsonReader reader,
            Type typeToConvert,
            JsonSerializerOptions options) =>
                Guid.Parse(reader.GetString()!);

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

然后尝试通过JsonConverter属性添加转换到属性。

public class Post
{
    [JsonConverter(typeof(GuidJsonConverter))]
    public Guid AuthorId { get; set; }

    public string Title { get; set; }
}

c# 在线

我创建了一个自定义转换器:

public sealed class JsonConverterGuid : System.Text.Json.Serialization.JsonConverter<Guid>
{
    public override Guid Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        if (reader.TryGetGuid(out Guid value))
        {
            Console.WriteLine("guid");
            return value;
        }

        if (reader.TryGetString(out string str))
        {
            Console.WriteLine("string");
            return Guid.Parse(str);
        }

        throw new FormatException("The JSON value is not in a supported Guid format.");
    }

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

public static class Ext
{
    public static bool TryGetString(this Utf8JsonReader je, out string parsed)
    {
        var(p, r) = je.TokenType switch
        {
            JsonTokenType.String => (je.GetString(), true),
            JsonTokenType.Null => (null, true),
            _ => (default, false)};
        parsed = p;
        return r;
    }
}

也许没有破折号的 GUID 不是标准,但我想与 Newtonsoft 兼容。 我正在发布答案,因为有人可能会遇到与我相同的错误。

并像这样使用它: https ://dotnetfiddle.net/K9UXpb

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM