Newtonsoft.Json筆記 -ContractResolver


介紹

ContractResolver能做什么:
為屬性添加一些序列化設置
自定義屬性名
有選擇的序列化屬性

CamelCasePropertyNamesContractResolver

Newtonsoft提供了CamelCasePropertyNamesContractResolver,繼承自ContractResolver,用於將屬性名轉成駝峰命名格式

//設置序列化時key為駝峰樣式
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.ContractResolver = new CamelCasePropertyNamesContractResolver();

案例

為屬性添加一些序列化設置

//為屬性添加JsonConverter
public class PropertyResolver : DefaultContractResolver
    {
        protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
        {
            var jsonProperty = base.CreateProperty(member, memberSerialization);

            if (jsonProperty.PropertyType == typeof(DateTime))
            {
                jsonProperty.Converter = new DateTimeZoneConverter();
                jsonProperty.ItemConverter = new DateTimeZoneConverter();
                //var objType = jsonProperty.DeclaringType;//所在類Type
                //jsonProperty.UnderlyingName;//屬性名
                //jsonProperty.PropertyName = "aaa";//修改序列化后的屬性名
                //var attributes = jsonProperty.AttributeProvider.GetAttributes(true);//獲取屬性上所有Attribute
                //jsonProperty.PropertyType = typeof(string);
            }
            return jsonProperty;
        }
    }

自定義屬性名

需求:序列化時需要將屬性名以下划線分隔並小寫的格式顯示,如DogName序列化為dog_name
繼承DefaultContractResolver,重寫ResolvePropertyName方法

    public class UnderlineSplitContractResolver : DefaultContractResolver
    {
        protected override string ResolvePropertyName(string propertyName)
        {
            return CamelCaseToUnderlineSplit(propertyName);
        }

        private string CamelCaseToUnderlineSplit(string name)
        {
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < name.Length; i++)
            {
                var ch = name[i];
                if (char.IsUpper(ch) && i > 0)
                {
                    var prev = name[i - 1];
                    if (prev != '_')
                    {
                        if (char.IsUpper(prev))
                        {
                            if (i < name.Length - 1)
                            {
                                var next = name[i + 1];
                                if (char.IsLower(next))
                                {
                                    builder.Append('_');
                                }
                            }
                        }
                        else
                        {
                            builder.Append('_');
                        }
                    }
                }

                builder.Append(char.ToLower(ch));
            }

            return builder.ToString();
        }
    }
    public class Person
    {
        public string Name { get; set; }
        public string DogName { get; set; }
        [JsonProperty("cat_name_1")]
        public string CatName { get; set; }
    }
        static void Main(string[] args)
        {
            JsonSerializerSettings settings = new JsonSerializerSettings
            {
                ContractResolver = new UnderlineSplitContractResolver()
            };
            Person p1 = new Person
            {
                Name = "fan",
                DogName = "ahuang",
                CatName = "nainiu"
            };
            var json = JsonConvert.SerializeObject(p1, settings);
            Console.WriteLine(json);//輸出:{"name":"fan","dog_name":"ahuang","cat_name_1":"nainiu"}
            Console.ReadKey();
        }

控制屬性是否序列化

根據某些場景,可能A場景輸出A,B,C三個屬性,B場景輸出E,F屬性。雖然實際中不一定存在這種需求,但是json.net依然可以支持該特性。
繼承默認的DefaultContractResolver類,傳入需要輸出的屬性,retain表示props是需要保留的字段還是要排除的字段

public class LimitPropsContractResolver : DefaultContractResolver
    {
        string[] props = null;

        bool retain;

        /// <summary>
        /// 構造函數
        /// </summary>
        /// <param name="props">傳入的屬性數組</param>
        /// <param name="retain">true:表示props是需要保留的字段  false:表示props是要排除的字段</param>
        public LimitPropsContractResolver(string[] props, bool retain=true)
        {
            //指定要序列化屬性的清單
            this.props = props;

            this.retain = retain;
        }

        protected override IList<JsonProperty> CreateProperties(Type type,

        MemberSerialization memberSerialization)
        {
            IList<JsonProperty> list =
            base.CreateProperties(type, memberSerialization);
            //只保留清單有列出的屬性
            return list.Where(p => {
                if (retain)
                {
                    return props.Contains(p.PropertyName);
                }
                else
                {
                    return !props.Contains(p.PropertyName);
                }      
            }).ToList();
        }
        public int Age { get; set; }

        [JsonIgnore]
        public bool IsMarry { get; set; }

        public string Sex { get; set; }
  string[] propNames = null;
  if (p.Age > 10)
  {
    propNames = new string[] { "Age", "IsMarry" };
  }
  else
  {
      propNames = new string[] { "Age", "Sex" };
  }
  jsetting.ContractResolver = new LimitPropsContractResolver(propNames);
  Console.WriteLine(JsonConvert.SerializeObject(p, Formatting.Indented, jsetting));


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM