如何在System.Text.Json的自定义JsonConverter中获取Utf8JsonReader的属性路径
问题描述
使用NewtonSoft时,我们可以通过reader.Path获取JSON路径,但System.Text.Json未提供该属性。
现有自定义DateTime转换器代码如下:
namespace API.JsonConverters { using System; using System.Text.Json; using System.Text.Json.Serialization; /// <summary> /// 用DateTime.Parse复现Newtonsoft的行为 /// </summary> public class DateTimeConverterUsingDateTimeParse : JsonConverter<DateTime> { public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { try { return DateTime.Parse(reader.GetString(), styles: System.Globalization.DateTimeStyles.RoundtripKind); } catch (FormatException) { // 我们需要让Path变量自动填充,这样中间件捕获错误时可以正确填充ModelState错误 throw new JsonException("无效的DateTime格式,请使用RoundTripKind格式(MM-DD-YYYY)"); } } public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) { writer.WriteStringValue(value.ToString("o")); } } }
如何在自定义JsonConverter的Read()方法内获取当前解析的JSON路径,使得抛出的异常同时包含自定义消息和Path属性?
解决方案
方案1:依赖框架自动填充(最常用,无需额外代码)
你完全不用在转换器里手动拿Path,System.Text.Json本身就帮你做了这件事:
- ASP.NET Core场景下,输入格式化器捕获到转换器抛出的
JsonException后,会自动把当前解析的Path、行号这些属性塞到异常里,你上层拿到的异常直接就能读Path - 直接调用
JsonSerializer.Deserialize的场景,.NET 5+版本的序列化器也会自动做这个填充
你现在的代码其实已经满足要求,抛出去的异常最终都会带正确的Path值,不用改核心逻辑。
方案2:转换器内部直接获取Path(特殊场景用)
如果你确实需要在Read方法里就拿到Path使用,可以通过反射读取Utf8JsonReader的内部状态拼接,也可以用.NET 7+新增的JsonTypeInfo相关API获取,简化实现示例如下:
private static string GetCurrentJsonPath(ref Utf8JsonReader reader) { var pathBuilder = new System.Text.StringBuilder(); // 可通过reader.CurrentDepth获取当前节点深度,结合反射读取的父节点名称拼接完整路径 // .NET 7+可直接配合JsonSerializerContext的类型元数据快速拼接路径 // 这里可以根据自己的业务需求完善拼接逻辑 return pathBuilder.ToString(); }
内容的提问来源于stack exchange,提问作者Victorio Berra
相关产品推荐
相关产品推荐

