Specifying default value for a property in relation to other property in Json.NET

非 Y 不嫁゛ 提交于 2020-01-03 03:39:04

问题


I am wondering if there is a way to set default value for a property in relation to other property of the same class in Json.NET e.g like this:

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

What I am trying to accomplish here is to populate End with DateTime value that is one hour later than Start in cases e.g when deserializing json to domain model and End value is missing or null. Like this:

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

The way I am doing it now is just inspecting later in code if End value is null in my domain object and if it is - populating it with desired value.

Is it feasible the way proposed in code sample or is there maybe a better simpler way except for the manual checking as in paragraph above?


回答1:


As specified in the JSON standard, a JSON object is an unordered set of name/value pairs, so in general Json.NET does not allow one property to be set relative to another. Json.NET is a streaming, single-pass deserializer and there's no guarantee which will appear first in the JSON.

However, when your object specifies use of a parameterized constructor via, e.g., the [JsonConstructor] attribute, Json.NET will pre-load the JSON properties and their values then construct the object with the deserialized values. This affords an opportunity to set the End property relative to the Start property:

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

Notes:

  • The names of the constructor arguments must be the same as the names of the properties, modulo case. This is how Json.NET matches constructor arguments with JSON properties.

  • Note that the End property is of type DateTime while the end constructor argument is of type DateTime?. When "End" is missing from the JSON, Json.NET will pass in a null value into the constructor, which can be checked for to properly initialize the End time relative to the Start.

  • If you don't want to serialize the End property when it is exactly one hour later than the start, you can use conditional property serialization:

    public bool ShouldSerializeEnd()
    {
        return End != Start.AddHours(1);
    }
    
  • The constructor does not need to be public when marked with [JsonConstructor]. Properties not passed into the constructor will be populated after construction as per usual deserialization.

Sample fiddle.




回答2:


If you are using C# 6 then probably you can do like [* Not sure if this is what you are looking to achieve]

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


来源:https://stackoverflow.com/questions/49659528/specifying-default-value-for-a-property-in-relation-to-other-property-in-json-ne

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!