【问题标题】:Is there a way to access customParameters object[] from within a custom JsonConverter class implementation?有没有办法从自定义 JsonConverter 类实现中访问 c​​ustomParameters object[]?
【发布时间】:2021-08-25 13:36:18
【问题描述】:

我编写了一个名为 CompententsConverter 的自定义 JsonConverter,它工作正常,但是我很好奇是否有一种方法可以使用备用构造函数,该构造函数接受 params object[] converterParameters 并从相应的属性。

同样,我不确定如何实际检索 JsonConverter 类定义中的参数,或者是否可以使用 JsonConverter 属性来执行此操作。

在模型内部,带有理论参数的属性,其中some_parameter_hereconstant expression 的占位符:

[JsonProperty("components")]
[JsonConverter(typeof(ComponentsConverter), some_parameter_here)]
public List<ComponentModel> Components { get; set; }

ComponentsConverter自定义JsonConverter:

public class ComponentsConverter : JsonConverter
{   
    public override bool CanConvert (Type t) => t == typeof(List<ComponentModel>);

    public override object ReadJson (JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        // ... any way to access params object[] customParameters here?
    }
    public override void WriteJson (JsonWriter writer, object value, JsonSerializer serializer)
    {
        // ...
    }
}

如果能够使用这些额外的参数为特定模型属性定义一些自定义转换行为,那就太好了。

【问题讨论】:

  • [JsonConverter(typeof(ComponentsConverter), "custom_string_value", someCustomObject)] 无法编译,因为属性参数must be a constant expression。那么您的问题是如何在JsonConverterAttribute.ConverterParameters 中传递非常量值? 还是您的问题是如何从转换器内部访问JsonConverterAttribute.ConverterParameters跨度>
  • @dbc 我可以接受它们是常量,这些只是占位符示例(已更新为更清晰),用于显示我想要传递东西的位置,是的,我不确定如何访问它们从转换器内部
  • 好吧,Json.NET 只是调用Activator.CreateInstance(ConverterType, ConverterParameters),因此转换器参数被传递到转换器的构造函数中。您可以在那里记住它们并在 ReadJson() 和 WriteJson() 中使用它们。参见例如Customising Json.NET serialisation based on compile time typedotnetfiddle.net/CjRRtn
  • @dbc 太棒了,如果您将此作为答案发布,我会奖励给您,最好也将您的代码粘贴到答案中

标签: .net-core json.net model-binding custom-attributes jsonconvert


【解决方案1】:

Json.NET 基本上只是调用Activator.CreateInstance(ConverterType, ConverterParameters) [1] 所以转换器参数被传递到转换器的构造函数中。您可以在那里记住它们并在ReadJson()WriteJson() 中使用它们,例如像这样:

public class ComponentsConverter : JsonConverter
{   
    public string CustomString { get; init; }

    public ComponentsConverter(string customString)
    {
        // Remember the converter parameters for use in WriteJson() and ReadJson()
        this.CustomString = customString;
    }

    public override bool CanConvert (Type t) => t == typeof(List<ComponentModel>);

    public override void WriteJson (JsonWriter writer, object value, JsonSerializer serializer)
    {
        // Customize the serialized contents using the CustomString passed in to the constructor
        writer.WriteValue(CustomString);
    }
    
    public override object ReadJson (JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        // ...
    }
}

对于应用于集合项的转换器,请使用JsonPropertyAttribute.ItemConverterTypeJsonPropertyAttribute.ItemConverterParameters。例如:

[JsonProperty("components",
              ItemConverterType = typeof(ComponentConverter), 
              ItemConverterParameters = new object [] { "custom_string_value" })]

然后:

public class ComponentConverter : JsonConverter
{   
    public string CustomString { get; init; }

    public ComponentConverter(string customString)
    {
        // Remember the converter parameters for use in WriteJson() and ReadJson()
        this.CustomString = customString;
    }

    public override bool CanConvert (Type t) => t == typeof(ComponentModel);

    public override void WriteJson (JsonWriter writer, object value, JsonSerializer serializer)
    {
        // Customize the serialized contents using the CustomString passed in to the constructor
        writer.WriteValue(CustomString);
    }
    
    public override object ReadJson (JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        // ...
    }
}

演示小提琴herehere


脚注:

[1]:我在这里有点过于简单化了。它实际上使用代码生成技术动态生成和缓存委托,这些委托与Activator.CreateInstance() 做同样的事情,但没有后期绑定反射的性能损失。参见例如ExpressionReflectionDelegateFactory.ObjectConstructor&lt;object&gt; CreateParameterizedConstructor(MethodBase method).

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-06
    • 2011-03-19
    • 1970-01-01
    • 2016-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多