【问题标题】:Json.NET CamelCasePropertyNameContractResolver not working with private property settersJson.NET CamelCasePropertyNameContractResolver 不适用于私有属性设置器
【发布时间】:2016-11-18 22:26:08
【问题描述】:

我正在使用 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,这是意料之外的。如果我将设置器公开,那么它可以正常工作。

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

这里明显的答案是只保持 setter 公开,但如果我想要/需要让 setter 私有,我怎样才能让 CamelCasePropertyNameContractResolver 与私有 setter 一起工作?我做错了什么,还是这可能是一个错误?

【问题讨论】:

    标签: c# json.net


    【解决方案1】:

    你可以通过写一个自定义的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
        }
    }
    

    顺便说一句: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. 不正确。如果您的属性具有公共设置器和获取器,则反序列化将忽略使用默认设置时的情况(这是我在此答案中使用的。我的 ContractResolver 还包括反序列化过程中的私有属性;仅此而已).....

    查看我使用相同 ContractResolver 的另一个问题:What am I doing wrong with JSON.NET's JsonConvert

    【讨论】:

    • @LB 感谢您的快速回复以及关于反序列化如何与私人二传手一起工作的澄清。所以我的选择是在每个属性上使用 JsonProperty 和私有设置器,或者使用自定义的 ContractResolver,就像您发布的那样,因为它包含私有设置器?
    猜你喜欢
    • 2012-01-25
    • 2016-08-24
    • 2015-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-25
    • 1970-01-01
    • 2014-05-21
    相关资源
    最近更新 更多