自定義Json序列化
阿新 • • 發佈:2022-05-24
public class ObjectConverter<T> : JsonConverter { public override bool CanConvert(Type objectType) { return true; } public override bool CanWrite { get { var type = typeof(T); returntype.IsClass; } } public override bool CanRead { get { return true; } } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {throw new NotImplementedException("Unnecessary because CanRead is false.The type will skip the converter."); } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { JObject containerObj = new JObject(); var properties = value.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);string enumPropStrName = string.Empty; List<string> enumPropNames = new List<string>(); foreach (var prop in properties) { var val = prop.GetValue(value); if (prop.PropertyType.IsEnum || (prop.PropertyType.IsGenericType && prop.PropertyType.GenericTypeArguments[0].IsEnum)) { if (properties.Count(x => string.Compare(x.Name, (prop.Name + "Str"), true) == 0) > 0) { enumPropStrName = prop.Name + "Str"; var first = properties.First(x => string.Compare(x.Name, enumPropStrName, true) == 0); if (containerObj.Properties().Count(x => x.Name == enumPropStrName) <= 0) { containerObj.Add(enumPropStrName, val.GetEnumDescription()); } else { containerObj[enumPropStrName] = val.GetEnumDescription(); } enumPropNames.Add(enumPropStrName); } else if (properties.Count(x => string.Compare(x.Name, (prop.Name + "Desc"), true) == 0) > 0) { enumPropStrName = prop.Name + "Desc"; var first = properties.First(x => string.Compare(x.Name, enumPropStrName, true) == 0); if (containerObj.Properties().Count(x => x.Name == enumPropStrName) <= 0) { containerObj.Add(enumPropStrName, val.GetEnumDescription()); } else { containerObj[enumPropStrName] = val.GetEnumDescription(); } enumPropNames.Add(enumPropStrName); } } else if (prop.PropertyType.IsClass && prop.PropertyType != typeof(string)) { JToken itemObj = null; if (val.GetType().GetInterfaces()?.Count(x => x == typeof(IEnumerable)) > 0) { itemObj = JArray.FromObject(val); } else { itemObj = JObject.FromObject(val); } if (containerObj.Properties().Count(x => x.Name == prop.Name) <= 0) { containerObj.Add(prop.Name, itemObj); } else { containerObj[prop.Name] = itemObj; } } else { var attr = prop.GetCustomAttribute<PropertySerilizerAttribute>(); if (attr != null) { val = attr.Convert(val, value); } JToken jVal = null; if (val != null) { jVal = JToken.FromObject(val); } if (!enumPropNames.Contains(prop.Name)) { if (containerObj.Properties().Count(x => x.Name == prop.Name) <= 0) { containerObj.Add(prop.Name, jVal); } else { containerObj[prop.Name] = jVal; } } } } containerObj.WriteTo(writer); } } public abstract class PropertyConverter { public abstract object Convert(object source, object obj); } public class DatePropertyConverter : PropertyConverter { public override object Convert(object source, object obj) { if (source != null && (source.GetType() == typeof(DateTime) || source.GetType() == typeof(DateTime?))) { return ((DateTime)source).ToString("yyyy-MM-dd"); } return null; } } public class DateTimePropertyConverter : PropertyConverter { public override object Convert(object source, object obj) { if (source != null && (source.GetType() == typeof(DateTime) || source.GetType() == typeof(DateTime?))) { return ((DateTime)source).ToString("yyyy-MM-dd HH:mm:ss"); } return null; } } /// <summary> /// 屬性序列化 /// </summary> [AttributeUsage(AttributeTargets.Property)] public class PropertySerilizerAttribute : Attribute { protected PropertyConverter Converter { get; set; } public PropertySerilizerAttribute(Type type) { if (type == typeof(PropertyConverter) || type?.BaseType == typeof(PropertyConverter)) { Converter = (PropertyConverter)Activator.CreateInstance(type); } } public object Convert(object source, object obj) { return Converter?.Convert(source, obj); } }