当前位置: 首页 > article >正文

Newtonsoft.Json对象转JSON字符串全集

需求:对象转为JSON字符串时可以同时满足以下5点。

1、同一个类中不同字段支持自定义日期格式,如:“2024-10-01”,“2024-10-01 12:12:12”;

2、string、datetime 为null时转为空字符串;int、decimal为null时转为0;对象为null时转为{};集合为null时转为[]; (PS:.Net8中Newtonsoft日期类型不支持空字符串)

3、long类型可以转为字符串;

4、枚举可以用“value、name、display” 做为json字符串的值;

5、小数点可以保留完整。

测试环境:

.Net5,.Net8

现实如下:

第1/3步:自定义ActionResult

public class CustomsJsonResult : ActionResult
{

    public object Value { get; private set; }  
    public string ContentType { get;  set; }
    public CustomsJsonResult(object _value){

        Value = _value;
    }
    /// <summary>
    /// 时间默认格式
    /// </summary>
    public string formatter = "yyyy-MM-dd HH:mm:ss";

    /// <summary>
    ///枚举转换
    /// </summary>
    public bool StringEnumConverter = false;
    public override void ExecuteResult(ActionContext context)
    {
        if (context == null)
        {
            context.HttpContext.Response.WriteAsync("{}");
        }
        var response = context.HttpContext.Response;
         response.ContentType =  string.IsNullOrEmpty(ContentType) ? "application/json": ContentType;
        var jsonSerizlizerSetting = new JsonSerializerSettings() {
            //设置取消循环引用
            MissingMemberHandling = MissingMemberHandling.Ignore,
            ReferenceLoopHandling = ReferenceLoopHandling.Ignore,

            //设置日期的格式为:yyyy-MM-dd
            DateFormatString = formatter,
          

            //自定义的解析协议
            ContractResolver = new NullToEmptyStringResolver()
           
        };

        if (StringEnumConverter)
        {
            //转换枚举
            CamelCaseNamingStrategy _CamelCaseNamingStrategy = new CamelCaseNamingStrategy { ProcessExtensionDataNames = true };
            //转换时使用枚举jsonProperty    [JsonConverter(typeof(EnumPropertyNameConverter)]
            jsonSerizlizerSetting.Converters.Add(new Models.EnumPropertyNameConverter { });
            //数字转为字符串  [JsonConverter(typeof(StringEnumConverter)]
            jsonSerizlizerSetting.Converters.Add(new StringEnumConverter { NamingStrategy = _CamelCaseNamingStrategy });
        }
        //日期转换格式
        jsonSerizlizerSetting.Converters.Add(new DateTimeFormat());//默认时间格式处理
        jsonSerizlizerSetting.Converters.Add(new DateFormat());//默认时间格式处理
        //时间转换格式
        //long转为字符串
        jsonSerizlizerSetting.Converters.Add(new Models.NumberToStrConverter { });
        //jsonSerizlizerSetting.Converters.Add(new DecimalPrecisionConverter(6));
   
        //序列化CardData出现内存溢出
        var json = JsonConvert.SerializeObject(Value, Formatting.None, jsonSerizlizerSetting);
        context.HttpContext.Response.WriteAsync(json);
    }

}

第2/3步:自定义解析协议,这里主要实现null转换。


    /// <summary>
    /// JSON自定义解析协议
    /// </summary>
    public class NullToEmptyStringResolver : Newtonsoft.Json.Serialization.DefaultContractResolver
    {
        protected override IValueProvider CreateMemberValueProvider(System.Reflection.MemberInfo member)
        {
            if (member.MemberType == MemberTypes.Property)
            {
                var pi = (PropertyInfo)member;
                if (
                pi.PropertyType == typeof(string)
                     || pi.PropertyType.BaseType == typeof(object)
                    || pi.PropertyType == typeof(DateTime)
                    || pi.PropertyType == typeof(DateTime?)
                    || pi.PropertyType == typeof(decimal?)
                    )
                {
                    return new NullableJsonValueProvider(pi);
                }
            }
            return base.CreateMemberValueProvider(member);
        }
    }


    //    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    //    {
    //        return type.GetProperties()
    //                .Select(p => {
    //                    var jp = base.CreateProperty(p, memberSerialization);
    //                    jp.ValueProvider = new NullToEmptyStringValueProvider(p);
    //                    return jp;
    //                }).ToList();
    //    }
    //}


    /// <summary>
    ///空值序列化提供程序
    /// </summary>
    public class NullableJsonValueProvider : IValueProvider
    {
        private static readonly string _defaultValue = string.Empty;

        private readonly PropertyInfo _propertyInfo;

        public NullableJsonValueProvider(PropertyInfo propertyInfo)
        {
            _propertyInfo = propertyInfo;
        }

        public void SetValue(object target, object value)
        {
            _propertyInfo.SetValue(target, value);
        }

        public object GetValue(object target)
        {
            var result = _propertyInfo.GetValue(target);
            if (result != null)
            {
                return result;
            }

            if (_propertyInfo.PropertyType == typeof(string)
                || _propertyInfo.PropertyType == typeof(DateTime)
                || _propertyInfo.PropertyType == typeof(DateTime?)
                )
            {
                //请注意,.Net8环境中Newtonsoft已经限制日期类型为空字符串,所以暂时放弃日期类型转为空字符串
                return _defaultValue;
            }
            //decimal型转为0
            else if (_propertyInfo.PropertyType == typeof(Nullable<decimal>))
                return 0M;
            //int型转为0
            else if (_propertyInfo.PropertyType == typeof(Nullable<int>))
                return 0;
            //集合转为[]
            else if (_propertyInfo.PropertyType.IsGenericType)
            {
                return new List<Newtonsoft.Json.Linq.JObject>(0);
            }
            //对象转为{}
            else if (_propertyInfo.PropertyType.BaseType == typeof(object))
            {
                if (_propertyInfo.PropertyType != typeof(string) && result == null)
                {
                  return  new Newtonsoft.Json.Linq.JObject();
                }
            }
            return result;

        }
    }

第3/3步:定义转换器

//yyyy-MM-dd日期的格式 
public class DateFormat : JsonConverter
 {
     public string format = "yyyy-MM-dd";

     public DateFormat()
     {
        
     }

     public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
     {
         if (value is DateTime dateTime)
         {
             writer.WriteValue(dateTime.ToString(format));
         }
         else
         {
             writer.WriteNull();
         }
     }

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

         if (reader.TokenType == JsonToken.String)
         {
             string text = reader.Value.ToString();
             if (DateTime.TryParse(text, out DateTime dateTime))
             {
                 return dateTime;
             }
         }

         throw new Exception($"Cannot convert {reader.TokenType} to {objectType}.");
     }

     public override bool CanConvert(Type objectType)
     {
         return objectType == typeof(DateTime);
     }
 }

//yyyy-MM-dd HH:mm:ss日期的格式
 public class DateTimeFormat : JsonConverter
 {
     public string format = "yyyy-MM-dd HH:mm:ss";

     public DateTimeFormat()
     {

     }

     public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
     {
         if (value is DateTime dateTime)
         {
             writer.WriteValue(dateTime.ToString(format));
         }
         else
         {
             writer.WriteNull();
         }
     }

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

         if (reader.TokenType == JsonToken.String)
         {
             string text = reader.Value.ToString();
             if (DateTime.TryParse(text, out DateTime dateTime))
             {
                 return dateTime;
             }
         }

         throw new Exception($"Cannot convert {reader.TokenType} to {objectType}.");
     }

     public override bool CanConvert(Type objectType)
     {
         return objectType == typeof(DateTime);
     }
 }



    /// <summary>
    /// 数字类型转为字符串
    /// </summary>
    public sealed class NumberToStrConverter : JsonConverter
    {
        /// <summary>
        /// 转换成字符串的类型
        /// </summary>
        private readonly NumberConverterShip _ship;

        /// <summary>
        /// 大数据json序列化重写实例化
        /// </summary>
        public NumberToStrConverter()
        {
            _ship = (NumberConverterShip)0xFF;
        }

        /// <summary>
        /// 大数据json序列化重写实例化
        /// </summary>
        /// <param name="ship">转换成字符串的类型</param>
        public NumberToStrConverter(NumberConverterShip ship)
        {
            _ship = ship;
        }

        /// <inheritdoc />
        /// <summary>
        /// 确定此实例是否可以转换指定的对象类型。
        /// </summary>
        /// <param name="objectType">对象的类型。</param>
        /// <returns>如果此实例可以转换指定的对象类型,则为:<c>true</c>,否则为:<c>false</c></returns>
        public override bool CanConvert(Type objectType)
        {
            var typecode = Type.GetTypeCode(objectType.Name.Equals("Nullable`1") ? objectType.GetGenericArguments().First() : objectType);
            switch (typecode)
            {
                case TypeCode.Int64:
                    return (_ship & NumberConverterShip.Int64) == NumberConverterShip.Int64;
              //  case TypeCode.Decimal:
                  //  return (_ship & NumberConverterShip.Decimal) == NumberConverterShip.Decimal;
              //  case TypeCode.Double:
                 //   return (_ship & NumberConverterShip.Double) == NumberConverterShip.Double;
               // case TypeCode.UInt64:
                 //   return (_ship & NumberConverterShip.UInt64) == NumberConverterShip.UInt64;
               // case TypeCode.Single:
                 //   return (_ship & NumberConverterShip.Single) == NumberConverterShip.Single;
                default: return false;
            }
        }

        /// <inheritdoc />
        /// <summary>
        /// 读取对象的JSON表示。
        /// </summary>
        /// <param name="reader">从 <see cref="T:Newtonsoft.Json.JsonReader" /> 中读取。</param>
        /// <param name="objectType">对象的类型。</param>
        /// <param name="existingValue">正在读取的对象的现有值。</param>
        /// <param name="serializer">调用的序列化器实例。</param>
        /// <returns>对象值。</returns>
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            if (reader.TokenType == JsonToken.Null)
            {
                return "";
            }

            return AsType(reader.Value.ToString(), objectType);
        }


        /// <summary>
        /// 字符串格式数据转其他类型数据
        /// </summary>
        /// <param name="input">输入的字符串</param>
        /// <param name="destinationType">目标格式</param>
        /// <returns>转换结果</returns>
        public static object AsType(string input, Type destinationType)
        {
            try
            {
                var converter = TypeDescriptor.GetConverter(destinationType);
                if (converter.CanConvertFrom(typeof(string)))
                {
                    return converter.ConvertFrom(null, null, input);
                }

                converter = TypeDescriptor.GetConverter(typeof(string));
                if (converter.CanConvertTo(destinationType))
                {
                    return converter.ConvertTo(null, null, input, destinationType);
                }
            }
            catch
            {
                return null;
            }
            return null;
        }

        /// <inheritdoc />
        /// <summary>
        /// 写入对象的JSON表示形式。
        /// </summary>
        /// <param name="writer">要写入的 <see cref="T:Newtonsoft.Json.JsonWriter" /> 。</param>
        /// <param name="value">要写入对象值</param>
        /// <param name="serializer">调用的序列化器实例。</param>
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            if (value == null)
            {
                writer.WriteNull();
            }
            else
            {
                var objectType = value.GetType();
                var typeCode = Type.GetTypeCode(objectType.Name.Equals("Nullable`1") ? objectType.GetGenericArguments().First() : objectType);
                switch (typeCode)
                {
                    case TypeCode.Int64:
                        writer.WriteValue(((long)value).ToString());
                        break;
                    //case TypeCode.Decimal:
                     //  writer.WriteValue(((decimal)value).ToString("f6"));
                      //  break;
                  //  case TypeCode.Double:
                      //  writer.WriteValue(((double)value).ToString("f4"));
                     //   break;
                   // case TypeCode.Single:
                     //   writer.WriteValue(((float)value).ToString("f2"));
                      //  break;
                   // default:
                      //  writer.WriteValue(value.ToString());
                      // break;
                }
            }
        }

.Net MVC项目使用演示:  

        protected ActionResult Json(object data,string ContentType = "application/json", string formatter= "yyyy-MM-dd HH:mm:ss",bool StringEnumConverter=false) {
            var res= new CustomsJsonResult(data)
            {
                ContentType = ContentType,
                StringEnumConverter = StringEnumConverter,
                formatter = formatter
            };
            return res;
        }

其中的data就是我们要转为json字符串的数据 。


http://www.kler.cn/a/310796.html

相关文章:

  • 记录日志中logback和log4j2不能共存的问题
  • 解决C盘空间不足的三种方案
  • Oracle RAC的thread
  • 灵活就业,真的等同于失业吗?“三无人员”如何齐短板获贷款
  • VSCode中python插件安装后无法调试
  • qt QFrame详解
  • 解决已经安装过requests库,却导入不了
  • 规律题总结(持续更新)
  • 大数据Flink(一百一十八):Flink SQL水印操作(Watermark)
  • CISP备考题库(四)
  • Docker日志管理
  • 爆改YOLOv8|使用MobileNetV4替换yolov8的Backbone
  • 53.【C语言】 字符函数和字符串函数(strcmp函数)
  • 温故--javaweb
  • MySQL行锁的实践
  • Gitee丝滑版本:成功在新电脑添加新文件
  • WebGL中的纹理映射:为虚拟世界穿上华丽的外衣
  • KNN算法与实战案例详解
  • 基于51单片机的自动清洗系统(自动洗衣机)
  • 【QT】系统-上
  • ​补​充​元​象​二​面​
  • Hexo框架学习——从安装到配置
  • SpringBoot:解析excel
  • PowerBI 关于FILTERS函数和VALUES函数
  • Spring模块详解Ⅳ(Spring ORM和Spring Transaction)
  • RedisTemplate混用带来的序列化问题