public class ObjectConverter<T> : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return true;
        }

        public override bool CanWrite
        {
            get
            {
                var type = typeof(T);
                return type.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);
        }
    }

 

posted on 2022-05-24 11:12  不知勿言  阅读(215)  评论(0编辑  收藏  举报