using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Newtonsoft.Json.Serialization; using YLErp.Commons; using YLErp.Helpers; namespace System { /// /// JSON序列化/反序列化帮助类(使用json.net) /// public static class JsonHelper { /// /// 将JSON字符串反序列化为对象,如果json字符串为null或空字符串,返回default(T) /// public static T ToObject(string json) { return string.IsNullOrWhiteSpace(json) ? default : JsonConvert.DeserializeObject(json, settings[(int)SerializeSetting.all]); } /// /// 将JSON字符串反序列化为对象,如果json字符串为null或空字符串,返回default(T) /// public static T Parse(string json) { return string.IsNullOrWhiteSpace(json) ? default : JsonConvert.DeserializeObject(json, settings[(int)SerializeSetting.all]); } /// /// 将JSON字符串反序列化为对象,如果json字符串为null或空字符串,返回default(T) /// public static T Deserialize(string json) { return string.IsNullOrWhiteSpace(json) ? default : JsonConvert.DeserializeObject(json, settings[(int)SerializeSetting.all]); } public static T DeserializeIgnoreNull(string json) { var settings = new JsonSerializerSettings { Error = (obj, args2) => { args2.ErrorContext.Handled = true; } }; return string.IsNullOrWhiteSpace(json) ? default : JsonConvert.DeserializeObject(json, settings); } //--------------------------------------------------------------------------------- /// /// 将对象序列化为JSON格式,如果对象为null,返回string.empty /// public static string ToJson(this object obj, bool ignoreNullValue = true, bool camelCase = false) { if (obj == null) { return string.Empty; } if (obj is Collections.Specialized.NameValueCollection nv) { obj = nv.AllKeys.ToDictionary(k => k, k => nv[k]); } else if (obj is IEnumerable arr && arr.Count() == 0) { return "[]"; } var setting = SerializeSetting.none; if (ignoreNullValue) { setting = SerializeSetting.ignoreNull; } if (camelCase) { setting |= SerializeSetting.camelCase; } return JsonConvert.SerializeObject(obj, settings[(int)setting]); } /// /// 将对象序列化为JSON格式,如果对象为null,返回string.empty /// public static string Stringify(object obj, bool ignoreNullValue = true, bool camelCase = false) { return ToJson(obj, ignoreNullValue, camelCase); } /// /// 将对象序列化为JSON格式,如果对象为null,返回string.empty /// public static string Serialize(object obj, bool ignoreNullValue = true, bool camelCase = false) { return ToJson(obj, ignoreNullValue, camelCase); } //--------------------------------------------------------------------------------- /// /// /// public static JsonSerializerSettings GetDefaultSettings() { var setting = new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore }; setting.Converters.Insert(0, DateOnlyJsonConverter.Default); return setting; } //--------------------------------------------------------------------------------- static readonly JsonSerializerSettings[] settings; static JsonHelper() { settings = new JsonSerializerSettings[1 + (int)SerializeSetting.all]; var defaultSettings = new JsonSerializerSettingsEx(); settings[(int)SerializeSetting.none] = defaultSettings; settings[(int)SerializeSetting.ignoreNull] = defaultSettings.Clone().Set(n => n.NullValueHandling = NullValueHandling.Ignore); settings[(int)SerializeSetting.camelCase] = defaultSettings.Clone().Set(n => n.ContractResolver = new CamelCasePropertyNamesContractResolver()); settings[(int)(SerializeSetting.ignoreNull | SerializeSetting.camelCase)] = defaultSettings.Clone().Set(n => { n.NullValueHandling = NullValueHandling.Ignore; n.ContractResolver = new CamelCasePropertyNamesContractResolver(); }); foreach (var s in settings) { if (s.Converters != null) { s.Converters.Insert(0, DateOnlyJsonConverter.Default); } else { s.Converters = new List { DateOnlyJsonConverter.Default }; } } } class JsonSerializerSettingsEx : JsonSerializerSettings { public JsonSerializerSettingsEx() { DateFormatString = "yyyy-MM-dd HH:mm:ss"; ReferenceLoopHandling = ReferenceLoopHandling.Ignore; } public JsonSerializerSettingsEx Set(Action setter) { setter(this); return this; } public JsonSerializerSettingsEx Clone() { return (JsonSerializerSettingsEx)MemberwiseClone(); } } /// /// json序列化配置枚举 /// enum SerializeSetting { none = 0, ignoreNull = 1, camelCase = 2, all = ignoreNull | camelCase } } /// /// 支持解析单个或数组格式到集合 /// 在IEnumerable[T]泛型定义的字段上加JsonConverterAttribute /// [JsonConverter(typeof(SingleOrArrayConverter))] /// public class SingleOrArrayConverter : JsonConverter { public override bool CanConvert(Type objectType) { return objectType == typeof(IEnumerable); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var token = JToken.Load(reader); if (token.Type == JTokenType.Array) { return token.ToObject(); } return new T[] { token.ToObject() }; } public override bool CanWrite { get { return false; } } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { throw new NotImplementedException(); } } /// /// 支持解析单个或数组格式到集合(空字符串将被过滤掉) /// public class StringArrayConverter : SingleOrArrayConverter { public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var token = JToken.Load(reader); if (token.Type == JTokenType.Array) { return token.ToObject().Where(n => !string.IsNullOrWhiteSpace(n)).ToArray(); } var str = token.ToObject(); return string.IsNullOrWhiteSpace(str) ? Array.Empty() : new[] { str }; } } /// /// /// class DateOnlyJsonConverter : JsonConverter { public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { writer.WriteValue(value?.ToString()); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var nullable = ReflectionHelper.IsNullableType(objectType); if (reader.TokenType == JsonToken.Null) { if (nullable) { return null; } return new YcDateOnly(DateTime.MinValue); } if (reader.TokenType == JsonToken.Date) { return new YcDateOnly((DateTime)reader.Value); } if (reader.TokenType != JsonToken.String) { throw new JsonSerializationException($"Unexpected token parsing date. Expected String, got {reader.TokenType},value:{reader.Value}"); } var dateText = reader.Value?.ToString(); if (string.IsNullOrWhiteSpace(dateText)) { if (nullable) { return null; } return DateTime.MinValue; } var dt = DateTime.Parse(dateText, Globalization.CultureInfo.InvariantCulture); return new YcDateOnly(dt); } public override bool CanRead => true; public override bool CanConvert(Type objectType) { return objectType == typeof(YcDateOnly) || objectType == typeof(YcDateOnly?); } public static readonly DateOnlyJsonConverter Default; static DateOnlyJsonConverter() { Default = new DateOnlyJsonConverter(); } } /// /// 用于格式化double数据 /// public class DoubleJsonWriteConverter : JsonConverter { readonly OtcFormatOption _format; public DoubleJsonWriteConverter(int minDecimals, int maxDecimals) { if (minDecimals < 0) { minDecimals = 0; } if (maxDecimals < minDecimals) { maxDecimals = minDecimals; } _format = new OtcFormatOption { minDecimals = minDecimals, maxDecimals = maxDecimals, grouping = false, percent = false, rounded = true }; } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { if (value == null) { writer.WriteNull(); } else if (value is double d) { writer.WriteValue(_format.FormatValue(d)); } else { var d2 = (double?)value; writer.WriteValue(_format.FormatValue(d2.Value)); } } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { throw new NotImplementedException(); } public override bool CanRead => false; public override bool CanConvert(Type objectType) { return objectType == typeof(double) || objectType == typeof(double?); } } }