在Json.NET中指定与其他属性相关的属性的默认值

时间:2018-04-04 20:06:50

标签: c# json.net

我想知道是否有办法在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 值,该值比开始晚一小时,例如在反序列化时json到域模型和结束值缺失或为null。像这样:

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

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

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

2 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:1)

JSON standard中所述,JSON对象是一个 无序 名称/值对,所以一般来说Json.NET不允许相对于另一个属性设置一个属性。 Json.NET是一个流式单通道反序列化器,并且不能保证它首先出现在JSON中。

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

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; }
}

注意:

  • 构造函数参数的名称必须与属性的名称相同,模数为case。这就是Json.NET如何将构造函数参数与JSON属性匹配。

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

  • 如果您不希望序列化Start属性,当它比开始时间晚一个小时时,您可以使用conditional property serialization

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

示例fiddle