Reputation: 15055
This is following an example based on code from this question (albeit for Serialization). Is it possible to override all Required.Always
to be Required.Default
(i.e. "optional"), and allow me to deserialize an object regardless of the "required" attributes?
public class OverrideToDefaultContractResolver : DefaultContractResolver
{
protected override JsonObjectContract CreateObjectContract(Type objectType)
{
var contract = base.CreateObjectContract(objectType);
contract.ItemRequired = Required.Default;
return contract;
}
}
public class MyClass
{
[JsonProperty("MyRequiredProperty", Required = Required.Always, NullValueHandling = NullValueHandling.Ignore)]
public string MyRequiredProperty { get; set; }
}
public static void Test()
{
var settings = new JsonSerializerSettings { ContractResolver = new OverrideToDefaultContractResolver() };
MyClass obj = JsonConvert.DeserializeObject<MyClass>(@"{""Nope"": ""Hi there""}", settings);
Console.WriteLine($"Json property: {obj.MyRequiredProperty}");
}
Upvotes: 3
Views: 2891
Reputation: 116786
In general, with Json.NET the precedence of settings is:
Your OverrideToDefaultContractResolver
cancels Required
attributes applied at the object level, but not at the individual property level. As the latter take precedence over the former, they need to be cancelled also. The following contract resolver does the job:
public class OverrideToDefaultContractResolver : DefaultContractResolver
{
protected override JsonProperty CreateProperty(System.Reflection.MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
property.Required = Required.Default;
return property;
}
protected override JsonObjectContract CreateObjectContract(Type objectType)
{
var contract = base.CreateObjectContract(objectType);
contract.ItemRequired = Required.Default;
return contract;
}
protected override JsonProperty CreatePropertyFromConstructorParameter(JsonProperty matchingMemberProperty, ParameterInfo parameterInfo)
{
var property = base.CreatePropertyFromConstructorParameter(matchingMemberProperty, parameterInfo);
property.Required = Required.Default;
return property;
}
}
Notes:
The contract resolver in the linked answer was originally designed to force all properties to be required unless explicitly marked otherwise - a reasonable default behavior for f#, which generally disallows null values.
You may want to cache the contract resolver for best performance.
Demo fiddle here.
Upvotes: 7