Can Json.NET populate readonly fields in a class?

后端 未结 3 1698
灰色年华
灰色年华 2020-12-18 00:06

I haven\'t seen much information about Json.NET supporting deserializing objects with readonly fields. I do notice that the .NET DataContract and DataMember att

相关标签:
3条回答
  • 2020-12-18 00:14

    afai can see changing a field to readonly results in a null value after deserialization. I had a working sample for another question (modified as shown below), and that's the behaviour I see.

    public class NameAndId
    {
        public string name;
        public int id; 
    }
    
    public class Data
    {
        public NameAndId[] data;
    }
    
    public class Target
    {
        public string id;
        public readonly NameAndId from;
        public DateTime updated_time;
        public readonly string message;
        public Data likes;
    }
    
    public class Program
    {
        static void Main(string[] args)
        {
            string json = File.ReadAllText(@"c:\temp\json.txt");
            Target newTarget = JsonConvert.DeserializeObject<Target>(json);
        }
    }
    
    0 讨论(0)
  • 2020-12-18 00:15

    Not the most elegant solution, but you can extend the DefaultConstractResolver to do it:

    public class ContractResolver : DefaultContractResolver
    {
        protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
        {
            var property = base.CreateProperty(member, memberSerialization);
            property.Writable = CanSetMemberValue(member, true);
            return property;
        }
    
        public static bool CanSetMemberValue(MemberInfo member, bool nonPublic)
        {
            switch (member.MemberType)
            {
                case MemberTypes.Field:
                    var fieldInfo = (FieldInfo)member;
    
                    return nonPublic || fieldInfo.IsPublic;
                case MemberTypes.Property:
                    var propertyInfo = (PropertyInfo)member;
    
                    if (!propertyInfo.CanWrite)
                        return false;
                    if (nonPublic)
                        return true;
                    return (propertyInfo.GetSetMethod(nonPublic) != null);
                default:
                    return false;
            }
        }
    }
    

    I have just remove one little check from the CanSetMemberValue method. Unfortunately it's neither virtual nor an instance method, so I had to override CreateProperty as well.

    0 讨论(0)
  • 2020-12-18 00:26

    This can be done now. Declare your properties using the JsonProperty attribute, and ensure that they have a protected set declared:

    [JsonProperty("Name")] public string Name {get; protected set;}
    

    This didn't work for me when using only a get, but works perfectly with the protected set.

    0 讨论(0)
提交回复
热议问题