C# Json.net反序列化中的强制构造函数参数值

C# Json.net反序列化中的强制构造函数参数值,c#,json.net,json-deserialization,C#,Json.net,Json Deserialization,是否可以强制Json.net传递构造函数参数的默认值 我尝试使用自定义的ContractResolver来覆盖CreateConstructorParameters和CreatePropertyFromConstructorParameter方法,并将返回的JsonProperty.DefaultValue属性设置为我所需的值和DefaultValueHandling属性设置为DefaultValueHandling.Populate 通过重写CreateObjectContract方法,我可以

是否可以强制Json.net传递构造函数参数的默认值

我尝试使用自定义的
ContractResolver
来覆盖
CreateConstructorParameters
CreatePropertyFromConstructorParameter
方法,并将返回的
JsonProperty.DefaultValue
属性设置为我所需的值和
DefaultValueHandling
属性设置为
DefaultValueHandling.Populate

通过重写
CreateObjectContract
方法,我可以看到匹配的
CreatorParameters
属性都包含我的默认值。但是,我仍然得到一个传递给构造函数的
null

我甚至尝试将属性上的
转换器设置为一个只返回所需默认值的转换器,但仍然没有成功

以下是ConstractResolver代码:

public class DataControllerContractResolver : DefaultContractResolver
{
    ///The desired default value
    private readonly IDataController _dataController;

    private readonly Type _dataControllerType;
    private readonly JsonConverter<IDataController> _converter;

    public DataControllerContractResolver(IDataController dataController)
    {
        _dataController = dataController;
        _dataControllerType = dataController.GetType();
        _converter = SimpleJsonConverter<IDataController>.From((reader, controller, arg3) => _dataController, (writer, controller, arg3) => {});
    }

    protected override IList<JsonProperty> CreateConstructorParameters(ConstructorInfo constructor, JsonPropertyCollection memberProperties)
    {
        var props = base.CreateConstructorParameters(constructor, memberProperties);

        foreach (var prop in memberProperties.Where(p => p.PropertyType.IsAssignableFrom(_dataControllerType)).ToList())
        {
            prop.DefaultValue = _dataController;
            prop.Converter = _converter;
            prop.DefaultValueHandling = DefaultValueHandling.Populate;
            prop.Ignored = false;
        }

        foreach (var prop in props.Where(p => p.PropertyType.IsAssignableFrom(_dataControllerType)).ToList())
        {
            prop.DefaultValue = _dataController;
            prop.Converter = _converter;
            prop.DefaultValueHandling = DefaultValueHandling.Populate;
            prop.Ignored = false;
        }


        return props;
    }

    protected override JsonProperty CreatePropertyFromConstructorParameter(JsonProperty matchingMemberProperty, ParameterInfo parameterInfo)
    {
        var prop = base.CreatePropertyFromConstructorParameter(matchingMemberProperty, parameterInfo);

        if (prop.PropertyType.IsAssignableFrom(_dataControllerType))
        {
            prop.DefaultValue = _dataController;
            prop.Converter = _converter;
            prop.MemberConverter = _converter;
            prop.DefaultValueHandling = DefaultValueHandling.Populate;
            prop.Ignored = false;
        }

        return prop;
    }

    protected override JsonObjectContract CreateObjectContract(Type objectType)
    {
        var contract = base.CreateObjectContract(objectType);
        return contract;
    }
}
公共类DataControllerContractResolver:DefaultContractResolver
{
///所需的默认值
专用只读IDataController\u数据控制器;
私有只读类型_dataControllerType;
专用只读JsonConverter\u转换器;
公共DataControllerContractResolver(IDataControllerDataController)
{
_数据控制器=数据控制器;
_dataControllerType=dataController.GetType();
_converter=SimpleJsonConverter.From((读卡器、控制器、arg3)=>\u数据控制器(写入器、控制器、arg3)=>{});
}
受保护的重写IList CreateConstructorParameters(ConstructorInfo构造函数、JsonPropertyCollection成员属性)
{
var props=base.CreateConstructorParameters(构造函数、成员属性);
foreach(memberProperties.Where(p=>p.PropertyType.IsAssignableFrom(_dataControllerType)).ToList()中的var prop)
{
prop.DefaultValue=\u数据控制器;
prop.Converter=_Converter;
prop.DefaultValueHandling=DefaultValueHandling.Populate;
prop.Ignored=false;
}
foreach(props.Where(p=>p.PropertyType.IsAssignableFrom(_dataControllerType)).ToList()中的var prop)
{
prop.DefaultValue=\u数据控制器;
prop.Converter=_Converter;
prop.DefaultValueHandling=DefaultValueHandling.Populate;
prop.Ignored=false;
}
返回道具;
}
受保护的重写JsonProperty CreatePropertyFromConstructorParameter(JsonProperty matchingMemberProperty,ParameterInfo ParameterInfo)
{
var prop=base.CreatePropertyFromConstructorParameter(matchingMemberProperty,parameterInfo);
if(prop.PropertyType.IsAssignableFrom(_dataControllerType))
{
prop.DefaultValue=\u数据控制器;
prop.Converter=_Converter;
prop.MemberConverter=\u converter;
prop.DefaultValueHandling=DefaultValueHandling.Populate;
prop.Ignored=false;
}
返回道具;
}
受保护的重写JsonObjectContract CreateObjectContract(类型objectType)
{
var contract=base.CreateObjectContract(objectType);
退货合同;
}
}

如果我重写并输入,我可以使此工作正常。我没有您所有的类(没有
IDataController
),因此这里有一个简单的示例:

public class DefaultStringValueContractResolver : DefaultContractResolver
{
    public string DefaultStringValue { get; set; }

    public DefaultStringValueContractResolver(string defaultStringValue)
    {
        this.DefaultStringValue = defaultStringValue;
    }

    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        var properties = base.CreateProperties(type, memberSerialization);
        // Set all string properties to have a default value of "this is a default value"
        foreach (var property in properties.Where(p => p.PropertyType == typeof(string)))
        {
            property.DefaultValue = DefaultStringValue;
            property.DefaultValueHandling = DefaultValueHandling.Populate;
        }
        return properties;
    }
}
公共类DefaultStringValueContractResolver:DefaultContractResolver
{
公共字符串DefaultStringValue{get;set;}
public DefaultStringValueContractResolver(字符串defaultStringValue)
{
this.DefaultStringValue=DefaultStringValue;
}
受保护的重写IList CreateProperties(类型类型,MemberSerialization MemberSerialization)
{
var properties=base.CreateProperties(类型、成员序列化);
//将所有字符串属性设置为默认值“这是默认值”
foreach(properties.Where(p=>p.PropertyType==typeof(string))中的var属性)
{
property.DefaultValue=DefaultStringValue;
property.DefaultValueHandling=DefaultValueHandling.Populate;
}
归还财产;
}
}
然后:

public class TestClass
{
    const string DefaultStringValue = "This is a default string value";

    public string Property1 { get; set; }

    public string Property2 { get; set; }

    public static void Test()
    {
        var settings = new JsonSerializerSettings { ContractResolver = new DefaultStringValueContractResolver(DefaultStringValue) };
        var test = JsonConvert.DeserializeObject<TestClass>("{}", settings);
        Debug.Assert(test.Property1 == DefaultStringValue && test.Property2 == DefaultStringValue); // No assert
        Debug.WriteLine(JsonConvert.SerializeObject(test)); // Prints {"Property1":"This is a default string value","Property2":"This is a default string value"}
    }
}
公共类TestClass
{
const string DefaultStringValue=“这是一个默认字符串值”;
公共字符串属性1{get;set;}
公共字符串属性2{get;set;}
公共静态无效测试()
{
var settings=new JsonSerializerSettings{ContractResolver=new DefaultStringValueContractResolver(DefaultStringValue)};
var test=JsonConvert.DeserializeObject(“{}”,设置);
Assert(test.Property1==DefaultStringValue&&test.Property2==DefaultStringValue);//无Assert
Debug.WriteLine(JsonConvert.SerializeObject(test));//打印{“Property1”:“这是默认字符串值”,“Property2”:“这是默认字符串值”}
}
}

需要注意的一点是:如果默认值是引用类型,则包含该属性的类的所有实例都将具有引用同一默认值实例的默认值。

在没有找到解决此问题的内置解决方案后,我全力以赴,在Github上添加了默认值检查和一个。JamesNK(Json.net创建者)略有不同,但它在最新版本中可用

谢谢你写下这个答案。这可以确保属性设置为默认值。我的问题是,这不会将默认值传递给构造函数。使用TestClass,如果添加构造函数:
publictTestClass(stringproperty1,stringproperty2){…}
参数仍然为空。在浏览源代码之后,我发现,奇怪的是,填充构造函数params数组的方法只在Json属性中循环,并将它们与contract.CreatorParams进行比较,因此只有序列化的属性才能用于params。我相信