What am I doing wrong with JSON.NET's JsonConvert

前端 未结 4 2005
广开言路
广开言路 2021-01-27 04:56

json string

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

class

inter         


        
相关标签:
4条回答
  • 2021-01-27 05:01

    the members must be 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
    }
    
    0 讨论(0)
  • 2021-01-27 05:03

    You can try to change modificator from internal to public

    0 讨论(0)
  • 2021-01-27 05:13

    Change the properties to public. By default it does not deserialize non-public properties

    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
    }
    
    0 讨论(0)
  • 2021-01-27 05:19

    Json.Net, by default, only serializes/deserialzes public fileds and properties, but you can also do it without changing access modifiers from internal to public.

    Just use JsonProperty attribute

    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
    }
    

    (Without modifing the original class) You can even use ContractResolver to select which properties/fields should be used in serialization process

    EDIT

    Although this answer has already been accepted, I want to post a code where the original assembly can not be modified.

    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
        }
    }
    
    0 讨论(0)
提交回复
热议问题