【问题标题】:Custom JsonConverter with parameters in .NET Core.NET Core 中带有参数的自定义 JsonConverter
【发布时间】:2021-05-05 15:32:44
【问题描述】:

我编写了自己的 JsonConverter(使用 ASP.Net Core 3.1),打算在我的 DTO 上使用它。

在以前的版本(Newtonsoft.Json)中,您可以在自定义 JsonConverter 类上添加构造函数,并使用 JsonConverterAttribute 指定参数:

[JsonConverter(typeof(MyDecimalConverter), 3)]
public decimal MyProp { get; set; }

但是,在迁移到System.Text.Json.Serialization 之后,此选项不再存在。新的 JsonConverterAttribute 根本没有构造函数。

实现这一目标的新方法是什么?

【问题讨论】:

  • 您是否尝试访问文档?
  • 看起来这不是开箱即用的。 JsonConverterAttribute 与 ConverterParameters 没有任何相似之处。 migration guide 甚至没有提到编译时转换器属性。您可能需要根据需要对您的MyDecimalConverter 进行子类化,例如MyDecimalConverter3Digit
  • 如果您将转换器应用于类型而不是属性,我可以想象解决方法,但我看不出有任何方法让转换器知道应用了它的属性。跨度>
  • @PavelAnikhouski 是的,是吗?
  • @dbc 是的,到目前为止,这也是我的结论。虽然有点不那么优雅..

标签: json .net asp.net-core json.net


【解决方案1】:

对比Newtonsoft.JsonSystem.Text.Json.Serialization中的JsonConverterAttribute定义,可以发现:使用System.Text.Json.Serialization时,不允许输入转换器参数。

因此,正如 dbc 所说,您可以创建一个自定义 JsonConverter 来将小数转换为 3 位数字,如下所示:

public class MyDecimalConverter3Digit : JsonConverter<decimal>
{
    public override decimal Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        throw new NotImplementedException();
    }
    public override void Write(Utf8JsonWriter writer, decimal value, JsonSerializerOptions options)
    {
        writer.WriteStringValue(Decimal.Round(value, 3).ToString());
    }
}

然后,在 Startup.ConfigureServices 方法中注册 JsonConverter:

        services.AddControllersWithViews().AddJsonOptions(options =>
        {
            options.JsonSerializerOptions.Converters.Add(new MyDecimalConverter3Digit());
        }); 

之后你就可以在模型中使用它了,像这样:

public class Calculate
{
    public decimal Price { get; set; }
    [JsonConverter(typeof(MyDecimalConverter3Digit))]
    public decimal Rate { get; set; }
}

此外,您还可以将应用程序配置为使用 Newtonsoft.Json 序列化和反序列化 json。请参考以下步骤:

  1. 通过 NuGet 安装Microsoft.AspNetCore.Mvc.NewtonsoftJson 包或使用以下命令:

     Install-Package Microsoft.AspNetCore.Mvc.NewtonsoftJson
    
  2. AddControllersWithViews()末尾添加.AddNewtonsoftJson()方法,像这样:

     services.AddControllers().AddNewtonsoftJson();
     services.AddControllersWithViews().AddNewtonsoftJson();
     services.AddRazorPages().AddNewtonsoftJson(); 
    

    当您创建自定义转换器时,请记住使用 Newtonsoft 参考,而不是 System.Text.Json.Serialization。像这样:

    之后,您可以使用带参数的自定义转换器。

【讨论】:

  • 这是显而易见的做法(也是我最终所做的)。但它并没有回答这个问题,而且在我看来,为每个小数位数制作具体的类并不是很优雅。此外,不推荐使用 Newtownsoft,因为 System.Text.Json is the new way 这样做了。使用遗留库配置应用程序很可能会在以后引起问题。
  • 嗨@Oyvind,是的,你是对的。但是,目前System.Text.Json不允许添加参数,您可以考虑使用上述方法作为临时解决方法,您也可以考虑filing an issue,看看是否可以添加对您的场景的支持。
  • 之后您就可以在模型中使用它了... 您无需向Startup.ConfigureServices 注册转换器即可将其应用于模型。直接应用于属性的转换器优先,如Converter registration precedence 中所述。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-12
  • 2017-04-28
  • 2016-08-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多