我想知道是否有办法在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,如果是 - 用所需的值填充它。
代码示例中提出的方法是否可行,或者除了上面的段落中的手动检查之外,是否有更好的简单方法?
答案 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。