【问题标题】:Specifying default value for a property in relation to other property in Json.NET指定与 Json.NET 中其他属性相关的属性的默认值
【发布时间】:2018-04-05 05:37:57
【问题描述】:

我想知道是否有一种方法可以为某个属性设置与 Json.NET 中同一类的其他属性相关的默认值,例如:

public class JsonsoftExample
{
    [JsonProperty(Required = Required.Always)]
    public DateTime Start { get; set; }

    [JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
    [DefaultValue(Start.AddHours(1))]
    public DateTime End { get; set; }
}

我在这里尝试完成的是用 DateTime 值填充 End,该值比 Start 晚一小时,例如在反序列化时json 到域模型并且 End 值丢失或为空。像这样:

string json = "{\"Start\": \"2017-01-01T08:00:00+01:00\"}";
var deserialized = JsonConvert.DeserializeObject<JsonsoftExample>(json);

我现在这样做的方式只是稍后在代码中检查 End 值是否在我的域对象中为空,如果是 - 使用所需的值填充它。

代码示例中提出的方法是否可行,或者除了上面段落中的手动检查之外,是否有更好更简单的方法?

【问题讨论】:

    标签: c# json.net


    【解决方案1】:

    正如JSON standard 中所指定的,JSON 对象是一组 无序 名称/值对,因此通常 Json.NET 不允许一个属性相对于另一个设置。 Json.NET 是一个流式单通道反序列化器,无法保证哪个会首先出现在 JSON 中。

    但是,当您的对象通过例如[JsonConstructor] 属性指定使用参数化构造函数时,Json.NET 将预加载 JSON 属性及其值,然后使用反序列化值构造对象。这提供了相对于Start 属性设置End 属性的机会:

    public partial class JsonsoftExample
    {
        public JsonsoftExample() { }
    
        [JsonConstructor]       
        JsonsoftExample(DateTime start, DateTime? end)
        {
            this.Start = start;
            this.End = end ?? Start.AddHours(1);            
        }
    
        [JsonProperty(Required = Required.Always)]
        public DateTime Start { get; set; }
    
        public DateTime End { get; set; }
    }
    

    注意事项:

    • 构造函数参数的名称必须与属性名称相同,以大小写为模。这就是 Json.NET 将构造函数参数与 JSON 属性匹配的方式。

    • 请注意,End 属性的类型为 DateTime,而 end 构造函数参数的类型为 DateTime?。当 JSON 中缺少 "End" 时,Json.NET 会将 null 值传入构造函数,可以检查该值以正确初始化相对于 StartEnd 时间。

    • 如果你不想在End 属性比开始时间正好晚一小时时序列化,你可以使用conditional property serialization

      public bool ShouldSerializeEnd()
      {
          return End != Start.AddHours(1);
      }
      
    • 使用[JsonConstructor] 标记时,构造函数不需要公开。未传递给构造函数的属性将在构造后按照通常的反序列化填充。

    示例fiddle

    【讨论】:

      【解决方案2】:

      如果您使用的是 C# 6,那么您可能可以这样做 [* 不确定这是否是您想要实现的目标]

      [JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]    
      public DateTime End { get; set; } = Start.AddHours(1);
      

      【讨论】:

      • 不幸的是它不能编译。版本也没有用“=>”代替“=”
      • 已检查,仅当我删除 { get;放; } 并使用 =>,但它会覆盖 End 值,即使它提供了
      猜你喜欢
      • 2015-06-19
      • 1970-01-01
      • 2020-07-18
      • 1970-01-01
      • 2020-04-07
      • 2012-12-15
      • 1970-01-01
      • 2011-04-06
      • 1970-01-01
      相关资源
      最近更新 更多