I have a case where I'm trying to set up an object with pre-defined default values before incorporating existing json data (using JSON.net). In some cases it works, though I think this is entirely because of empty arrays. The one case where it doesn't, I'm using a base snippet of json for one of the properties.
To set the default values, I implemented the answer I from How to pass DefaultValue for custom class when deserializing with Json.net for my custom classes.
[In LINQPad]
void Main()
{
var appData = new AppData().Dump();
var defaultSettings = @"{ }";
appData = JsonConvert.DeserializeObject<AppData>(defaultSettings).Dump();
var data = @"{
""Ranges"": [
{
""Name"": ""Foo"",
""Minimum"": 110,
""Maximum"": 120,
""Include"": true
},
{
""Name"": ""Bar"",
""Minimum"": 125,
""Maximum"": 145,
""Include"": true
}
]
}";
JsonConvert.PopulateObject(data, appData, new JsonSerializerSettings() { ObjectCreationHandling = ObjectCreationHandling.Replace });
appData.Dump();
var output = JsonConvert.SerializeObject(appData, Newtonsoft.Json.Formatting.Indented).Dump();
}
public class AppData
{
[JsonDefaultValueAttribute(typeof(IEnumerable<RangeData>), @"[
{
""Name"": ""First"",
""Minimum"": 120,
""Maximum"": 145,
""Include"": true
},
{
""Name"": ""Second"",
""Minimum"": 125,
""Maximum"": 135,
""Include"": false
}
]")]
public IEnumerable<RangeData> Ranges
{
get;
set;
}
[JsonDefaultValueAttribute(typeof(IEnumerable<Highlight>), "[ ]")]
[JsonProperty(DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)]
public IEnumerable<Highlight> Highlights
{
get;
set;
}
[JsonDefaultValueAttribute(typeof(IEnumerable<string>), "[ ]")]
[JsonProperty(DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)]
public IEnumerable<string> Filters
{
get;
set;
}
}
public class RangeData
{
public string Name { get; set; }
public int Minimum { get; set; }
public int Maximum { get; set; }
public bool Include { get; set; }
}
public class Highlight
{
public string Text { get; set; }
public Brush Color { get; set; }
}
public class JsonDefaultValueAttribute : DefaultValueAttribute
{
public JsonDefaultValueAttribute(Type type, string json)
: base(ConvertFromJson(type, json))
{
}
private static object ConvertFromJson(Type type, string json)
{
var value = JsonConvert.DeserializeObject(json, type, new JsonSerializerSettings
{
MissingMemberHandling = MissingMemberHandling.Error,
NullValueHandling = NullValueHandling.Include,
DefaultValueHandling = DefaultValueHandling.Populate
});
return value;
}
}
Output from this is
AppData >
UserQuery+AppData
Ranges null
Highlights null
Filters null
AppData >
UserQuery+AppData
Ranges null
Highlights (0 items)
Filters (0 items)
AppData >
UserQuery+AppData
Ranges List<RangeData> (2 items) >
Name Minimum Maximum Include
Foo 110 120 True
Bar 125 145 True
Highlights (0 items)
Filters (0 items)
{
"Ranges": [
{
"Name": "Foo",
"Minimum": 110,
"Maximum": 120,
"Include": true
},
{
"Name": "Bar",
"Minimum": 125,
"Maximum": 145,
"Include": true
}
]
}
This appears to deserialize correctly, but only Highlights and Filters give me collections as expected. Stepping through the debug reveals the data is correctly parsed and put into the correct structure. Any insights to understand what I'm missing with respect to the collection with data?
EDIT: Added parameter to overwrite existing objects if there is data on call to PopulateObject