How to pass DefaultValue for custom class when deserializing with Json.net

ぃ、小莉子 提交于 2019-12-24 05:55:17

问题


I want to deserialize a JSON structure like this:

{
    "Name": "Foo",
    "bar": {
        "Name": "Bar",
        "DefaultableProperty": "default"
    }
}

... where it is optional to define "bar". And in the case that it is not defined, I want to load an object of type Bar with some default values.

Here are my class definitions for Foo and Bar

public class Foo
{
    [JsonConstructor]
    public Foo()
    {
        string bardefaults = @"{ ""Name"": ""defaultname""}";
        b = new Bar(bardefaults);
    }
    public string Name { get; set; }
    public Bar bar { get; set; }
}

public class Bar
{
    public Bar() { }
    public Bar(string json)
    {
        Bar copy = JsonConvert.DeserializeObject<Bar>(json);
        Name = copy.Name;
        DefaultableProperty = copy.DefaultableProperty;
    }
    public string Name { get; set; }

    [DefaultValue("default")]
    [JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
    public string DefaultableProperty { get; set; }
}

And here is my test method for deserializing some JSON:

[TestMethod]
public void CanDeserializeObjectWithDefaultValues()
{
     string s = @"{ 'Name': 'aname', 
                  }";
     Foo foo = JsonConvert.DeserializeObject<Foo>(s);
     Assert.AreEqual("aname", foo.Name);
     Assert.AreEqual("default", foo.bar.DefaultableProperty);
     Assert.IsNotNull(foo.bar.Name);
}

Using the code above I am able to deserialize an object of type Bar with it's default values. However, I would like to be able to use a DefaultValue for Foo.bar as I do for Bar.DefaultableProperty. I haven't been able to achieve this with the following syntax:

  • [DefaultValue(typeof(Bar), @"{ ""Name"": ""bar"" }")]
  • [DefaultValue(new Bar(@"{ ""Name"": ""bar"" }"))]

So my question is does Json.NET have some support for creation of a default custom object? If not, then what is the best way to approach this situation?


回答1:


What I did is created a new JsonDefaultValueAttribute attribute which derives from DefaultValueAttribute, and added a new ctor to support converting json-string value to target type as follows:

public class JsonDefaultValueAttribute : DefaultValueAttribute
{
    public JsonDefaultValue(string json, Type type) : base (ConvertFromJson(json, type))
    {            
    }

    private static object ConvertFromJson(string json, Type type)
    {
        var value = JsonConvert.DeserializeObject(json, type, new JsonSerializerSettings
        {
            MissingMemberHandling = MissingMemberHandling.Error,
            NullValueHandling = NullValueHandling.Include,
            DefaultValueHandling = DefaultValueHandling.Populate
        });

        return value;
    }
    ....
}

Now you can use the new attribute instead of using the default one.



来源:https://stackoverflow.com/questions/37641855/how-to-pass-defaultvalue-for-custom-class-when-deserializing-with-json-net

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