C# Json做配置文件, 抽象接口的序列化和反序列

做一些配置文件时常用到的功能,话不多説,直接上代码

使用的库是Newtonsoft,这个很常见了,安装之类的,这里就不赘述了

核心代码:

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

 /// <summary>
    /// 用于多态序列化
    /// </summary>
    public class PolyConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return true;
        }
#pragma warning disable CS8600 // 将 null 字面量或可能为 null 的值转换为非 null 类型。
#pragma warning disable CS8765 // 参数类型的为 Null 性与重写成员不匹配(可能是由于为 Null 性特性)。 
#pragma warning disable CS8604 // 引用类型参数可能为 null。
#pragma warning disable CS8603 // 可能返回 null 引用。
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            var jObject = JObject.Load(reader);
            foreach (var item in jObject.Properties())
            {

                Type type = Type.GetType(item.Name);

                var value = item.Value.ToObject(type);


                return value;

            }
            return null;
        }

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)

        {
            JObject jObject = new JObject();

            jObject.Add(value.GetType().FullName, JToken.FromObject(value));

            serializer.Serialize(writer, jObject);
        }
#pragma warning restore CS8603 // 可能返回 null 引用。
#pragma warning restore CS8604 // 引用类型参数可能为 null。
#pragma warning restore CS8765 // 参数类型的为 Null 性与重写成员不匹配(可能是由于为 Null 性特性)。
#pragma warning restore CS8600 // 将 null 字面量或可能为 null 的值转换为非 null 类型。
    }

    /// <summary>
    /// 用于多态列表的转化
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class PolyListConverter<T> : JsonConverter
    {
#pragma warning disable CS8600 // 将 null 字面量或可能为 null 的值转换为非 null 类型。
#pragma warning disable CS8765 // 参数类型的为 Null 性与重写成员不匹配(可能是由于为 Null 性特性)。 
#pragma warning disable CS8604 // 引用类型参数可能为 null。
#pragma warning disable CS8603 // 可能返回 null 引用。
        public override bool CanConvert(Type objectType)
        {
            return true;
        }
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            var jObject = JObject.Load(reader);
            List<T> values = new List<T>();
            foreach (var item in jObject.Properties())
            {
                Type type = Type.GetType(item.Name);
                var value = item.Value.ToObject(type);
                values.Add((T)value);
            }
            return values;
        }
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            var values = (List<T>)value;
            JObject jObject = new JObject();
            foreach (var item in values)
            {
                jObject.Add(item?.GetType().FullName, JToken.FromObject(item));
            }
            var p = jObject.Properties();
            //foreach (var item in p)
            //{
            //    Debug.Log(item.Name);
            //}
            serializer.Serialize(writer, jObject);
        }
#pragma warning restore CS8603 // 可能返回 null 引用。
#pragma warning restore CS8604 // 引用类型参数可能为 null。
#pragma warning restore CS8765 // 参数类型的为 Null 性与重写成员不匹配(可能是由于为 Null 性特性)。
#pragma warning restore CS8600 // 将 null 字面量或可能为 null 的值转换为非 null 类型。
    }

使用以及对应的情况

    public class JsonTest
    { 
        public void Test()
        {
            List<Monster> monsters = new List<Monster>()
            {
                new Monster()
                {
                    Name ="怪物1",
                    AttackMode = new WeaponAttack(),
                    MoveMode = new GroundMove(),
                },
                new Monster()
                {
                    Name ="怪物2",
                    AttackMode = new ClawAttack(),
                    MoveMode = new AirMove(),
                }
            };

            var json = JsonConvert.SerializeObject(monsters, Formatting.Indented);

            Console.WriteLine(json);
            var result = JsonConvert.DeserializeObject<List<Monster>>(json);
        }
    }


    public class Monster
    {
        //首先我们这里有个怪物,但是怪物的攻击和移动方式有很多种,所以对它进行抽象
        //当我们需要给这个怪物扩展攻击方式或者移动方式时
        //只需要继承基类,而且还可以通过反射的方式,获取所有的实现来进行配置
        public string Name { get; set; } = "None";

        [JsonConverter(typeof(PolyConverter))]
        public Attack? AttackMode { get; set; }  

        [JsonConverter(typeof(PolyConverter))]
        public Move? MoveMode { get; set; }
    }


    public abstract class Attack
    {
        public virtual string Weapon { get; set; } = "无";
    }
     
    public abstract class Move
    {
        public abstract string Walk { get; set; }  
    }

    //--------------------------- Attack
    public sealed class WeaponAttack: Attack
    {
        public override string Weapon { get; set; } = "使用武器攻击";
    }

    public sealed class ClawAttack : Attack
    {
        public override string Weapon { get; set; } = "使用爪子攻击";
    }


    //--------------------------- Move

    public sealed class GroundMove : Move
    {
        public override string Walk { get; set; } = "在地面上行走";
    }

    public sealed class AirMove : Move
    {
        public override string Walk { get; set; } = "在空中飞行";
    }

上述运行之后的结果

1.转换成json后的

 2.从json转换成对应实例

很方便吧

通过反射获取基类所有实现的方式,下篇再见

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值