thu*_*ug_ 15 c# json.net asp.net-core .net-6.0 minimal-apis
我有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));
});
Run Code Online (Sandbox Code Playgroud)
如果我尝试更改为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()
});
});
Run Code Online (Sandbox Code Playgroud)
我知道net5.0我可以用这个
services.AddControllers().AddNewtonsoftJson((options) => //options); // OR
services.AddMvc().AddNewtonsoftJson((options) => //options);
Run Code Online (Sandbox Code Playgroud)
但是,如果我在net6.0项目中像上面那样使用它,那么我就不再使用 MinimalApi 了?
Gur*_*ron 20
正如文档中提到的:
正文绑定源使用 System.Text.Json 进行反序列化。无法更改此默认值
所以我建议只使用System.Text.Json. 但如果确实需要,您可以尝试一些解决方法。
根据我的理解,最小 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);
}
}
Run Code Online (Sandbox Code Playgroud)
及用法:
class PostParams : BaseModel<PostParams>
{
[JsonProperty("prop")]
public int MyProperty { get; set; }
}
// accepts json body {"prop": 2}
app.MapPost("/pst", (PostParams po) => po.MyProperty);
Run Code Online (Sandbox Code Playgroud)
请注意,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));
}
}
Run Code Online (Sandbox Code Playgroud)
用法更改为:
class PostParams
{
[JsonProperty("prop")]
public int MyProperty { get; set; }
}
// accepts json body {"prop": 2}
app.MapPost("/pst", (Wrapper<PostParams> po) => po.Value.MyProperty);
Run Code Online (Sandbox Code Playgroud)
一些额外有用的链接:
services.AddControllers().AddNewtonsoftJson((options) => //options);| 归档时间: |
|
| 查看次数: |
21572 次 |
| 最近记录: |