使用 JSON.net(JsonConvert.SerializeObject 或 JsonConvert.DeSerializeObject)为缺少的复杂属性设置默认值

Posted

技术标签:

【中文标题】使用 JSON.net(JsonConvert.SerializeObject 或 JsonConvert.DeSerializeObject)为缺少的复杂属性设置默认值【英文标题】:Set Default value for missing Complex properties with JSON.net (JsonConvert.SerializeObject or JsonConvert.DeSerializeObject) 【发布时间】:2021-06-21 13:44:10 【问题描述】:

我有一个要求,我需要使用JsonPropertyDefaultValue 为以下复杂属性Instances 设置默认值。

我知道我们可以为以下链接中提到的原始属性实现此目的,但需要知道如何为复杂属性实现此目的。

Default value for missing properties with JSON.net

下面是我需要使用DefaultValue() 设置的默认Instances 值。请告诉我如何实现这一目标。

要设置为Instances属性的默认值:

Instance instance = new Instance();
instance.Name = "XYZ";
instance.MyProperty = 11;

List<Instance> Instances = new List<Instance>();
Instances.Add(instance);

代码sn-p:

public class DataSettings

  public DataSettings()
  
    Instances = new List<Instance>();
  

  [DefaultValue()] //How can I mention the above default value here ?
  [JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
  public List<Instance> Instances  get; set; 


public class Instance

  public string Name  get; set; 
  public int MyProperty  get; set; 

【问题讨论】:

【参考方案1】:

如您所见,属性仅支持常量值,因此您不能在属性中设置复杂值。如果你想在反序列化过程中为复杂属性设置一个默认值,一个好的方法是使用serialization callback方法,如下所示。

这个想法是向您的类添加一个方法,序列化程序将在对象的反序列化完成后调用该方法。回调必须是void 方法,接受StreamingContext 作为其唯一参数,并且必须使用[OnDeserialized] 属性进行标记。方法的名称无关紧要。 在回调方法中可以检查Instances列表是否被填充,如果没有,可以根据需要设置默认值。

public class DataSettings

    public DataSettings()
    
        Instances = new List<Instance>();
    

    public List<Instance> Instances  get; set; 

    [OnDeserialized]
    internal void SetDefaultValuesAfterDeserialization(StreamingContext context)
    
        if (Instances == null || !Instances.Any())
        
            Instances = new List<Instance>
            
                new Instance  Name = "XYZ", MyProperty = 11 
            ;
        
    

这是一个演示这个概念的工作小提琴:https://dotnetfiddle.net/uCGP5X

【讨论】:

谢谢布赖恩,但上述方法还有一个问题,对吧?如果我在构造函数中添加您的逻辑,那么如果我显式创建 DataSettings 对象,那么默认情况下 Instances 将在其列表中添加一个值,对吗?例如,如果我正在创建 DataSettings 的实例并添加下面的代码,那么我最终将为实例创建 2 个值,一个来自构造函数逻辑,另一个是我明确创建的。数据设置 dataSettings = new DataSettings(); dataSettings.Instances.Add(new Instance() Name = "XYZ" ); 我明白了。因此,您只希望在反序列化时填充默认值,而不是其他时间。在这种情况下,使用反序列化回调是一种更好的方法。我已经修改了答案。 感谢 Brian Rogers 的更新回复。有没有可能我可以使用 JsonCustomConverter 来传递默认实例,以便在反序列化期间它应该检查对象的某些属性是否为空或整个对象是否为空,然后使用默认实例并返回该实例。只是好奇知道有没有?

以上是关于使用 JSON.net(JsonConvert.SerializeObject 或 JsonConvert.DeSerializeObject)为缺少的复杂属性设置默认值的主要内容,如果未能解决你的问题,请参考以下文章

.Net使用Newtonsoft.Json.dll(JSON.NET)对象序列化成json反序列化json示例教程

Json.NET 入门

.NET(C#) Json.Net(newtonsoft)使用LINQ查询JSON数据

Newtonsoft.Json(Json.net) 的使用

如何使用 JSON.NET 通过 ASP.NET MVC 传递 JSON 日期值? [复制]

使用 Json.net 将 JSON 对象反序列化为动态对象