在NewtonSoft中,我們可以通過reader.Path獲得路徑。而System.Text.Json則沒有這個功能。
namespace API.JsonConverters
{
使用系統。
using System.Text.Json;
using System.Text.Json.Serialization;
// <summary>/span>
// 使用DateTime.Parse來復制Newtonsoft的作業方式。
// </summary>/span>
// < remarks>https://docs.microsoft.com/en-us/dotnet/standard/datetime/system-text-json-support</remarks>
public class DateTimeConverterUsingDateTimeParse : JsonConverter<DateTime>
{
public override DateTime Read(ref Utf8JsonReader readers, typeToConvert, JsonSerializerOptions options)。
{
try
{
return DateTime.Parse(reader.GetString(), styles: System.Globalization.DateTimeStyles.RoundtripKind)。)
}
catch (FormatException)
{
//我們必須這樣做以使Path變數自動填充,這樣當中間件捕捉到錯誤時,它將正確填充ModelState錯誤。
//https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-converters-how-to#error-handling
//https://github.com/dotnet/aspnetcore/blob/release/3.1/src/Mvc/Mvc.Core/src/Formatters/SystemTextJsonInputFormatter.cs#L79
throw new JsonException("Invalid DateTime. 請使用RoundTripKind(MM-DD-YYY)-https://docs.microsoft.com/en-us/dotnet/standard/base-types/how-to-round-trip-date-and-time-values")。
}
}
public override void Write(Utf8JsonWriter writer。DateTime value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToString("o"/span>))。
}
}
}
我怎樣才能獲得對當前路徑的訪問權,以便我能夠從我的自定義JsonConverter的Read()方法中拋出一個既有自定義訊息又有Path的例外?
uj5u.com熱心網友回復:
在JsonConverter中,你想拋出一個帶有自定義訊息的自定義例外,同時包括JSONPath資訊。 正如docs所解釋的,System.Text.Json只將路徑資訊附加到JsonException型別的例外中 - 而且只有當該例外沒有訊息的時候。 那么,如何才能將路徑資訊包含在內呢?
明顯的方法是,將路徑資訊包含在內。
明顯的方法是在JsonConverter<T>.Read()中獲取當前路徑,并將其傳遞給例外的建構式。 不幸的是,System.Text.Json并沒有將路徑提供給Read()或者Write()。 這可以通過檢查參考源來確認。 Utf8JsonReader目前甚至不知道路徑。它所知道的是容器型別(物件或陣列)的堆疊,使用BitStack成員Utf8JsonReader._bitStack,這是退出嵌套容器時正確處理其狀態轉換所需的最小值。 JsonSerializer確實跟蹤了當前的堆疊,通過ReadStack ref結構,它有一個JsonPath() 方法。 不幸的是,ReadStack是內部的,從未暴露給應用程式或Utf8JsonReader。
作為一種變通方法,你可以創建嵌套的例外,內部的例外是你需要的例外型別,外部的例外是一個JsonException,序列化器將把路徑填入其中。 下面是如何做到這一點的一個例子:
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)。
{
try
{
return DateTime.Parse(reader.GetString(),
樣式。System.Globalization.DateTimeStyles.RoundtripKind)。)
}
catch (FormatException)
{
var innerEx = new ProblemDetailsException("Invalid DateTime. 請使用RoundTripKind(MM-DD-YYY)-https://docs.microsoft.com/en-us/dotnet/standard/base-types/how-to-round-trip-date-and-time-values")。
throw new JsonException(null, innerEx)。
}
然后在更高的層次上,你可以捕獲JsonException,并拋出一個外部的ProblemDetailsException,例如像這樣:
public class JsonExtensions
{
public staticT Deserialize<T> (string json, JsonSerializerOptions options = default)
{
try
{
return JsonSerializer.Deserialize<T>(json, options)。
}
catch (JsonException ex) when (ex.InnerException is ProblemDetailsException innerException)
{
var finalException = new ProblemDetailsException(innerException.Message, ex.Path, ex)。
拋出 finalException。
}
}
注釋:
在這里我作為假設
ProblemDetailsException看起來像:public class ProblemDetailsException : System.Exception { public ProblemDetailsException(string message) : base(message) { } public ProblemDetailsException(>string message, Exception inner) 。base(message, inner) { } public ProblemDetailsException(string message。string path) : base(message) => this.Path = path。 public ProblemDetailsException(string message。string path, Exception inner) : base(message, inner) => this.Path = path; public string Path { get; } }你可以考慮使用
CultureInfo.InvariantCulture決議你的DateTime:return DateTime.Parse(reader.GetString(), 樣式。System.Globalization.DateTimeStyles.RoundtripKind, 提供者。System.Globalization.CultureInfo.InvariantCulture)。)按照目前的寫法,你的轉換器在不同的地區會有不同的功能。 或者,如果你真的想在當前的語言環境中進行決議,請在你的代碼中明確說明:
return DateTime.Parse(reader.GetString(), 樣式。System.Globalization.DateTimeStyles.RoundtripKind, 提供者。System.Globalization.CultureInfo.CurrentCulture)。)
示范性fiddle 這里.
。轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/307743.html
標籤:
