我在 .Net 中有一个 REST API,它返回以下对象:
public class MyDto
{
public string Name {get; set;}
public int Age {get; set;}
public string ContactNumber {get; set;}
}
我想实现一个自定义 JSON 转换器,我可以将其添加为属性。当响应的对象被序列化时,基于 HTTP 标头中的值,我想排除特定属性。
例如,如果我添加这样的属性:
public class MyDto
{
public string Name {get; set;}
[JsonConverter(typeof(CustomConverter))]
public int Age {get; set;}
public string ContactNumber {get; set;}
}
设置特定标头时的响应应该是:
{
"Name":"Name",
"ContactNumber":"1234567"
}
您需要另一种方法,因为转换器无法访问
HttpContext
。
从
System.Text.Json
版本7.0.0开始,您可以自定义JSON合约。
来自文档:
System.Text.Json 库为每个 .NET 类型构建一个 JSON 契约,它定义了类型应如何序列化和反序列化。
一个主题描述了您想要实现的目标:
修改:有条件地序列化属性
如何实现:修改属性的谓词。JsonPropertyInfo.ShouldSerialize
定义一个自定义属性,充当标记来定位应有条件排除的属性。
public class ConditionallyIncludedAttribute : Attribute
{ }
public class MyDto
{
public string Name { get; set; }
[ConditionallyIncluded]
public int Age { get; set; }
public string ContactNumber { get; set; }
}
设置一个自定义
DefaultJsonTypeInfoResolver
,为 DTO 模型上已标记有自定义属性的属性的 false
返回 ShouldSerialize
。
public sealed class CustomJsonTypeInfoResolver : DefaultJsonTypeInfoResolver
{
public override JsonTypeInfo GetTypeInfo(Type type, JsonSerializerOptions options)
{
var typeInfo = base.GetTypeInfo(type, options);
if (type.IsClass && type != typeof(string))
{
foreach (var property in typeInfo.Properties.Where(o =>
o.AttributeProvider!.GetCustomAttributes(false)?.Any(o => o is ConditionallyIncludedAttribute) ?? false
))
{
property.ShouldSerialize = (_, _) => false;
}
}
return typeInfo;
}
}
定义一个自定义
SystemTextJsonOutputFormatter
,使用自定义 JsonSerializerOptions
并安装此 CustomJsonTypeInfoResolver
。
此自定义格式化程序只能在存在预期的 HTTP 标头时应用 - 请参阅
CanWriteResult
覆盖。
public class CustomJsonOutputFormatter : SystemTextJsonOutputFormatter
{
public CustomJsonOutputFormatter()
: base(new JsonSerializerOptions()
{
TypeInfoResolver = new CustomJsonTypeInfoResolver()
// Other settings go here
})
{ }
public override bool CanWriteResult(OutputFormatterCanWriteContext context)
{
var myHeader = context.HttpContext.Request.Headers["MyHeader"].ToString();
return !string.IsNullOrEmpty(myHeader);
}
}
在
program.cs
中注册此自定义格式化程序
builder.Services.AddControllers(
o => o.OutputFormatters.Add(new CustomJsonOutputFormatter())
);