我有net6.0一個 api 最少的專案,我想使用NetwtonsoftJson而不是內置System.Text.Json庫來進行序列化和反序列化。
目前我有這個配置JsonOptions并且可以按預期作業
builder.Services.Configure<JsonOptions>(options =>
{
options.SerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
options.SerializerOptions.WriteIndented = true;
options.SerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles;
options.SerializerOptions.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase));
});
如果我嘗試更改為使用Newtonsoft.Json.JsonSerializerSettings如下所示的等效內容,則不會出現相同的行為。相反,它看起來像是使用默認System.Text.Json配置。
builder.Services.Configure<JsonSerializerSettings>(options =>
{
options.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
options.Converters.Add(
new StringEnumConverter
{
NamingStrategy = new Newtonsoft.Json.Serialization.CamelCaseNamingStrategy()
});
});
在net5.0我知道我可以使用這個
services.AddControllers().AddNewtonsoftJson((options) => //options); // OR
services.AddMvc().AddNewtonsoftJson((options) => //options);
但是,如果我在我的net6.0專案中像上面那樣使用它,那么我就不再使用 MinimalApi 了?
uj5u.com熱心網友回復:
根據我的理解,Minimal API 依賴于一些關于型別系結的約定。從我所看到的,他們搜索具有下一個簽名的方法 -ValueTask<TModel?> BindAsync(HttpContext context, ParameterInfo parameter)在型別上,否則將嘗試使用httpContext.Request.ReadFromJsonAsync內部使用System.Text.Json且無法更改的services.Add...().AddNewtonsoftJson((options) => //options);方法,因此方法將不起作用。
要使用,Newtonsoft.Json您可以嘗試下一個(除了通過 直接處理請求app.MapPost("/pst", (HttpContext c) => c.Request...)):
如果您可以控制需要使用它反序列化的所有類,您可以從一些通用基類繼承它們,這些基類將具有所需簽名的方法(您也可以使用帶有實作的靜態方法的介面):
public class BaseModel<TModel>
{
public static async ValueTask<TModel?> BindAsync(HttpContext context, ParameterInfo parameter)
{
if (!context.Request.HasJsonContentType())
{
throw new BadHttpRequestException(
"Request content type was not a recognized JSON content type.",
StatusCodes.Status415UnsupportedMediaType);
}
using var sr = new StreamReader(context.Request.Body);
var str = await sr.ReadToEndAsync();
return JsonConvert.DeserializeObject<TModel>(str);
}
}
和用法:
class PostParams : BaseModel<PostParams>
{
[JsonProperty("prop")]
public int MyProperty { get; set; }
}
// accepts json body {"prop": 2}
app.MapPost("/pst", (PostParams po) => po.MyProperty);
請注意,BaseModel<TModel>此示例中的實作非常幼稚,可能可以改進(HttpRequestJsonExtensions.ReadFromJsonAsync至少檢查一下)。
如果您無法控制模型或不想從某些基礎繼承它們,您可以考慮創建包裝器:
public class Wrapper<TModel>
{
public Wrapper(TModel? value)
{
Value = value;
}
public TModel? Value { get; }
public static async ValueTask<Wrapper<TModel>?> BindAsync(HttpContext context, ParameterInfo parameter)
{
if (!context.Request.HasJsonContentType())
{
throw new BadHttpRequestException(
"Request content type was not a recognized JSON content type.",
StatusCodes.Status415UnsupportedMediaType);
}
using var sr = new StreamReader(context.Request.Body);
var str = await sr.ReadToEndAsync();
return new Wrapper<TModel>(JsonConvert.DeserializeObject<TModel>(str));
}
}
并且用法更改為:
class PostParams
{
[JsonProperty("prop")]
public int MyProperty { get; set; }
}
// accepts json body {"prop": 2}
app.MapPost("/pst", (Wrapper<PostParams> po) => po.Value.MyProperty);
一些額外有用的鏈接:
- MVC 模型系結器- David Fowler。雖然我無法讓它為
services.AddControllers().AddNewtonsoftJson((options) => //options); - ParameterBinder - Damian Edwards 的類似方法
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/354935.html
