Newtonsoft.Json笔记


序列化设置的几种方式:

全局序列化:(在之后使用JsonConvert进行序列化时都有效)

            JsonConvert.DefaultSettings = new Func(() =>
            {
                Newtonsoft.Json.JsonSerializerSettings setting = new Newtonsoft.Json.JsonSerializerSettings();
                //日期类型默认格式化处理
                setting.DateFormatHandling = Newtonsoft.Json.DateFormatHandling.MicrosoftDateFormat;
                setting.DateFormatString = "yyyy-MM--dd HH:mm:ss";
                //空值处理
                setting.NullValueHandling = NullValueHandling.Ignore; 
                //setting.Converters.Add(new BoolConvert("是,否"));

                return setting;
            });

序列化时指定JsonSerializerSettings:

JsonSerializerSettings jsetting = new JsonSerializerSettings();
jsetting.DefaultValueHandling = DefaultValueHandling.Ignore;
jsetting.DateFormatString = "yyyy-MM---dd HH:mm:ss";

            Man2 man = new Man2
            {
                Name = "张三",
                DogName = "阿黄",
                Birthday = DateTime.Now
            };
            //new JsonConverter().
            string json = JsonConvert.SerializeObject(man, jsetting);

通过特性标签设置:

[JsonProperty(NullValueHandling=NullValueHandling.Ignore)]
 public Room room { get; set; }

忽略某些属性

通过在属性上添加[JsonIgnore]标签可以忽略序列化属性
也可以设置仅序列化某些属性:

[JsonObject(MemberSerialization.OptIn)]
    public class Person
    {
        [JsonProperty]
        public string Name { get; set; }

        public string Sex { get; set; }
    }

默认值处理

DefaultValueHandling.Ignore 序列化和反序列化时,忽略默认值
DefaultValueHandling.Include 序列化和反序列化时,包含默认值

JsonSerializerSettings jsetting = new JsonSerializerSettings();
jsetting.DefaultValueHandling = DefaultValueHandling.Ignore;//忽略默认值

空值处理

方式1:
 JsonSerializerSettings jsetting=new JsonSerializerSettings();
 jsetting.NullValueHandling = NullValueHandling.Ignore;//忽略空值

方式2:
[JsonProperty(NullValueHandling=NullValueHandling.Ignore)]
 public Room room { get; set; }

支持非公共成员

序列化时默认都是只处理公共成员,如果需要处理非公共成员,就要在该成员上加特性"JsonProperty"

[JsonProperty]
 private int Height { get; set; }

自定义序列化属性名称

[JsonProperty(PropertyName = "CName")]
     public string Name { get; set; }

动态决定属性是否序列化

根据不同场景选择要输出的属性,比如场景1需要序列化A、B、C属性,场景2序列化D、E属性
通过继承DefaultContractResolver类实现以上需求

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

        bool retain;

        /// 
        /// 构造函数
        /// 
        /// 传入的属性数组
        /// true:表示props是需要保留的字段  false:表示props是要排除的字段
        public LimitPropsContractResolver(string[] props, bool retain=true)
        {
            //指定要序列化属性的清单
            this.props = props;

            this.retain = retain;
        }

        protected override IList CreateProperties(Type type, MemberSerialization memberSerialization)
        {
            IList list =
            base.CreateProperties(type, memberSerialization);
            //只保留清单有列出的属性
            return list.Where(p => {
                if (retain)
                {
                    return props.Contains(p.PropertyName);
                }
                else
                {
                    return !props.Contains(p.PropertyName);
                }      
            }).ToList();
        }
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));

指定key的显示格式

可以执行key的显示格式为驼峰命名,或自定义输出

//设置序列化时key为驼峰样式
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
settings.Formatting = Formatting.Indented;//带缩进
 
string str = JsonConvert.SerializeObject(menus, settings);
Console.WriteLine(str);

循环引用处理

Newtonsoft.Json默认 已经处理过循环引用

//设置循环引用,及引用类型序列化的层数。
//注:目前在 EF core中目前不支持延迟加载,无所谓循环引用了
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.Formatting = Formatting.Indented;
settings.MaxDepth = 10; //设置序列化的最大层数
settings.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;//指定如何处理循环引用,None--不序列化,Error-抛出异常,Serialize--仍要序列化

枚举序列化成字符串

Newtonsoft提供了StringEnumConverter,它继承自JsonConverter,用于序列化时显示枚举的名称,而不是枚举值

public enum EType
    {
        [Description("type1")]
        类型1 = 1,
        [Description("type2")]
        类型2 = 2
    }
   public class TestResponseModel
    {
        [JsonConverter(typeof(StringEnumConverter))]//  DescriptionEnumJsonConverter
        public EType Type { get; set; }
    }

序列化后的结果:

{"Type":"类型1"}

如果想将输出内容改成枚举项上的[Description],可以将StringEnumConverter换成DescriptionEnumJsonConverter,代码如下

public class DescriptionEnumJsonConverter : StringEnumConverter
    {
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            if (reader.TokenType == JsonToken.Null)
            {
                return null;
            }

            try
            {
                if (objectType.IsEnum)
                {
                    return this.GetValue(objectType, reader.Value, reader.Value.ToString());
                }
                return reader.Value;
            }
            catch (Exception)
            {
                throw new Exception(string.Format("不能将枚举{1}的值{0}转换为Json格式.", reader.Value, objectType));
            }

        }

        /// 
        /// 判断是否为Bool类型
        /// 
        /// 类型
        /// 为bool类型则可以进行转换
        public override bool CanConvert(Type objectType)
        {
            return objectType.IsEnum;
        }

        public bool IsNullableType(Type type)
        {
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }

            return type.BaseType != null
                   && (type.BaseType.FullName == "System.ValueType"
                       && type.GetGenericTypeDefinition() == typeof(Nullable<>)
                      )
                   ;
        }

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            if (value == null)
            {
                writer.WriteNull();
                return;
            }
            Type type = value.GetType();
            if (type.IsEnum)
            {
                object bValue = GetEnumDescription(type, value);
                writer.WriteValue(bValue);

                //serializer.DateTimeZoneHandling = DateTimeZoneHandling.Utc;

            }
            else
            {
                writer.WriteValue(value);
            }
        }

        /// 
        /// 获取枚举描述
        /// 
        /// 枚举类型
        /// 枚举hasecode
        /// 
        private object GetEnumDescription(Type type, object value)
        {
            string name = System.Enum.GetName(type, value);
            if (name == null)
            {
                return value;
            }
            FieldInfo field = type.GetField(name);
            if (field == null)
            {
                return value;
            }

            var desc = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute;
            if (desc != null)
            {
                return desc.Description;
            }
            return value;
        }

        private object GetValue(Type type, object value, string description)
        {
            object result = null;
            var fieldInfo = type.GetFields(BindingFlags.Static | BindingFlags.Public).Where(t =>
            {
                var attr = t.GetCustomAttribute();
                if (attr != null)
                {
                    return attr.Description.Equals(description, StringComparison.CurrentCultureIgnoreCase);
                }
                return false;
            })
                                .FirstOrDefault();
            if (fieldInfo != null)
            {
                result = fieldInfo.GetValue(value);
            }
            return result ?? value;
        }
    }

序列化后的结果:

{"Type":"type1"}

自定义类型转换

参考:https://so.csdn.net/so/search?q=NewtonSoft.JSON官方手册中文版&t=blog&u=fanxiaojie119 (NewtonSoft.JSON官方手册中文版)