Json.NET CamelCasePropertyNameContractResolver不使用私有属性setter

时间:2016-11-18 22:26:09

标签: c# json.net

我正在使用Json.NET(8.0.3),我正在尝试将CamelCasePropertyNameContractResolver与JsonConvert.DeseralizeObject()一起使用,以便我可以使用驼峰大小写属性读取JSON。这是JSON的一个例子。

{ "name":"somename", "type":"sometype" }

以下是我尝试反序列化的课程:

public class MyClass {
    public string Name { get; private set; }
    public string Type { get; private set; }
}

如果我使用JsonConvert.DeseralizeObject,则Name和Type值为null,因为从技术上讲,类属性名称与JSON属性名称不匹配。这是预料之中的。如果我添加JsonProperty属性,那么它将正确反序列化(也是预期的)。

public class MyClass {
    [JsonProperty("name")]
    public string Name { get; private set; }
    [JsonProperty("type")]
    public string Type { get; private set; }
}

我不想将JsonProperty属性放在所有属性上,所以我尝试了CamelCasePropertyNameContractResolver。

JsonConvert.DefaultSettings = () => new JsonSerialierSettings {
    ContractResolver = new CamelCasePropertyNameContractResolver()
};

MyClass value = JsonConvert.DeserializeObject<MyClass>(json);

MyClass对象的Name和Type属性都是null,这是意外的。如果我公开setter那么它可以正常工作。

public class MyClass {
    public string Name { get; set; }
    public string Type { get; set; }
}

这里显而易见的答案是只保持setter公开,但如果我想/需要将setter设为私有,那么如何让CamelCasePropertyNameContractResolver与私有setter一起工作?我做错了什么,或者这是一个可能的错误?

1 个答案:

答案 0 :(得分:3)

您可以通过撰写自定义ContractResolver

来完成此操作
string json = @"{""name"":""somename"", ""type"":""sometype"" }";

var settings = new JsonSerializerSettings() { 
                         ContractResolver = new AllPropertiesContractResolver() };
var res = JsonConvert.DeserializeObject<MyClass>(json,settings);

public class MyClass
{
    public string Name { get; private set; }
    public string Type { get; private set; }
}
public class AllPropertiesContractResolver : DefaultContractResolver
{
    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        var props = type.GetProperties(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance)
                    .Select(x => new Newtonsoft.Json.Serialization.JsonProperty()
                    {
                        PropertyName = x.Name,
                        PropertyType = x.PropertyType,
                        Readable = true,
                        ValueProvider = new AllPropertiesValueProvider(x),
                        Writable = true
                    })
                    .ToList();


        return props;
    }
}

public class AllPropertiesValueProvider : Newtonsoft.Json.Serialization.IValueProvider
{
    PropertyInfo _propertyInfo;

    public AllPropertiesValueProvider(PropertyInfo p)
    {
        _propertyInfo = p;
    }

    public object GetValue(object target)
    {
        return _propertyInfo.GetValue(target);  //Serialization
    }

    public void SetValue(object target, object value)
    {
        _propertyInfo.SetValue(target, value, null); //Deserialization
    }
}

BTW:If I use JsonConvert.DeseralizeObject the Name and Type values are null because technically the class property names do not match the JSON property names.不正确。如果您的属性具有公共setter和getter,反序列化将忽略使用默认设置时的情况(这是我在此答案中使用的。我的ContractResolver还包括反序列化过程中的私有属性;这就是全部).....

请参阅我使用相同ContractResolver的其他问题:What am I doing wrong with JSON.NET's JsonConvert