[英]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 .JsonConverter1.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.JsonConverter1.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, Nullable1 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; }
}
我创建了一个自定义转换器:
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.