如何实现条件自定义Json转换器隐藏属性

问题描述 投票:0回答:1

我在 .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"
}
c# json.net .net-6.0 system.text.json jsonconverter
1个回答
0
投票

您需要另一种方法,因为转换器无法访问

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())
    );
© www.soinside.com 2019 - 2024. All rights reserved.