【问题标题】:What am I doing wrong with JSON.NET's JsonConvertJSON.NET 的 JsonConvert 我做错了什么
【发布时间】:2016-11-04 04:11:57
【问题描述】:

json 字符串

{
  "success": true,
  "challenge_ts": "2016-11-03T17:30:00Z",
  "hostname": "mydomain.com"
}

internal class reCaptchaResponse
{
    internal bool success { get; set; }
    internal DateTime challenge_ts { get; set; }  // timestamp of the challenge load (ISO format yyyy-MM-dd'T'HH:mm:ssZZ)
    internal string hostname { get; set; }        // the hostname of the site where the reCAPTCHA was solved
    internal string[] error_codes { get; set; }   // optional
}

尝试序列化

reCaptchaResponse responseObject = Newtonsoft.Json.JsonConvert.DeserializeObject<reCaptchaResponse>(jsonResult);

尝试失败...

Newtonsoft.Json.JsonConvert.SerializeObject(responseObject) 返回 {}

【问题讨论】:

  • jsonResult 的值是多少?
  • “尝试序列化”, DeserializeObject == Deserialize where SerializeObject == Serialize

标签: c# json json.net


【解决方案1】:

默认情况下,Json.Net 仅序列化/反序列化 public 文件和属性,但您也可以这样做,而无需将访问修饰符从 internal 更改为 public。

只需使用JsonProperty 属性

internal class reCaptchaResponse
{
    [JsonProperty]
    internal bool success { get; set; }
    [JsonProperty]
    internal DateTime challenge_ts { get; set; }  // timestamp of the challenge load (ISO format yyyy-MM-dd'T'HH:mm:ssZZ)
    [JsonProperty]
    internal string hostname { get; set; }        // the hostname of the site where the reCAPTCHA was solved
    [JsonProperty]
    internal string[] error_codes { get; set; }   // optional
}

(不修改原类)你甚至可以使用ContractResolver来选择在序列化过程中应该使用哪些属性/字段

编辑

虽然这个答案已经被接受,但是我想贴一个不能修改原始程序集的代码。

var settings = new JsonSerializerSettings() { 
                   ContractResolver = new AllPropertiesContractResolver() 
               };
reCaptchaResponse responseObject = 
                JsonConvert.DeserializeObject<reCaptchaResponse>(jsonResult ,settings);

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
    }
}

【讨论】:

    【解决方案2】:

    将属性更改为public。默认情况下它不会反序列化非公共属性

    internal class reCaptchaResponse
    {
        public bool success { get; set; }
        public DateTime challenge_ts { get; set; }  // timestamp of the challenge load (ISO format yyyy-MM-dd'T'HH:mm:ssZZ)
        public string hostname { get; set; }        // the hostname of the site where the reCAPTCHA was solved
        public string[] error_codes { get; set; }   // optional
    }
    

    【讨论】:

    • Because Newtonsoft.Json.JsonConvert isn't in the same assembly it can't access the internal properties. 似乎您缺少 Json.Net 大量使用的 Reflection
    • @L.B - 已更正
    【解决方案3】:

    成员必须是公开的

    internal class reCaptchaResponse
    {
        public bool success { get; set; }
    public DateTime challenge_ts { get; set; }  // timestamp of the challenge load (ISO format yyyy-MM-dd'T'HH:mm:ssZZ)
        public string hostname { get; set; }        // the hostname of the site where the reCAPTCHA was solved
        public  string[] error_codes { get; set; }   // optional
    }
    

    【讨论】:

      【解决方案4】:

      您可以尝试将修改器从内部更改为公开

      【讨论】:

        猜你喜欢
        • 2011-06-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-14
        • 2021-04-19
        • 2017-03-13
        • 2017-01-18
        • 2013-06-24
        • 1970-01-01
        相关资源
        最近更新 更多