c# 经过json.net中的JsonConverter进行自定义序列化与反序列化

https://www.cnblogs.com/yijiayi/p/10051284.htmlhtml

相信你们在工做中会常常碰见对json进行序列化与反序列化吧,但一般的序列化与反序列化中的json结构与c#中的类模型结构是相对应的,咱们是否能够在序列化一个对象时候,让咱们json的数据结构能按照本身的意愿,而没必要与该对象的数据结构同样呢?,好比说,一个对象,只有一个名为"ID"的int类型的属性,值为1,若是序列化该对象,则能获得json:{"ID":1},但我如今但愿获得的json的"ID"值是bool类型:{"ID":true}。要知足可以进行自定义序列化与反序列化的要求,咱们能够运用json.net中的转换器JsonConverter。json

  先来个简单的例子,就上面那个,一个对象,只有一个名为"ID"的int类型的属性,值为1,序列化该对象,若是ID值为1,则能获得json:{"ID":true},若是ID值不为1,获得json{"ID":false}。c#

  定义类:数据结构

        public class Model
        {
            public int ID { get; set; }
        }

  NuGet添加引用Newtonsoft.Json,再定义一个转换器类MyConverter,这个类要继承Newtonsoft.Json命名空间下的一个抽象类JsonConverter,咱们先来看下这个抽象类的成员,有两个属性与三个抽象方法:ide

  

在MyConverter中咱们要实现这三个抽象方法CanConvert()、ReadJson()、WriteJson(),并用特性[JsonConverter(typeof(MyConverter))]标记在咱们要自定义序列化的类Model上就好了,就像这样:函数

  

        [JsonConverter(typeof(MyConverter))]
        public class Model
        {
            public int ID { get; set; }
        } 

 

 

  在序列化Model对象的时候,程序会走到MyConverter下已经实现的WriteJson()方法,同理,反序列化会走到ReadJson()方法,而CanConvert方法是用于判断是否须要自定义序列化或者反序列化的,它的参数objectType对应着特性JsonConverter所标记类的对应Type类型。测试

  下面是MyConverter类的代码实现:spa

   

复制代码
        public class MyConverter : JsonConverter
        {
            //是否开启自定义反序列化,值为true时,反序列化时会走ReadJson方法,值为false时,不走ReadJson方法,而是默认的反序列化
            public override bool CanRead => false;
            //是否开启自定义序列化,值为true时,序列化时会走WriteJson方法,值为false时,不走WriteJson方法,而是默认的序列化
            public override bool CanWrite => true;

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

            public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
            {
                throw new NotImplementedException();
            }

            public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
            {
                //new一个JObject对象,JObject能够像操做对象来操做json
                var jobj = new JObject();
                //value参数其实是你要序列化的Model对象,因此此处直接强转
                var model = value as Model;
                if (model.ID != 1)
                {
                    //若是ID值为1,添加一个键位"ID",值为false
                    jobj.Add("ID",false);
                }
                else
                {
                    jobj.Add("ID", true);
                }
                //经过ToString()方法把JObject对象转换成json
                var jsonstr = jobj.ToString();
                //调用该方法,把json放进去,最终序列化Model对象的json就是jsonstr,由此,咱们就能自定义的序列化对象了
                writer.WriteValue(jsonstr);
            }
        }    
复制代码

  以后咱们在Main函数里进行测试:.net

  

复制代码
         static void Main(string[] args)
        {
            var model = new Model();
            model.ID = 1;
            var json = JsonConvert.SerializeObject(model);//因为ID值为1,获得json为{"ID":ture}

            Console.WriteLine(json);
            model.ID = 2;
            json = JsonConvert.SerializeObject(model);//因为ID值不为1,获得json为{"ID":false}
            Console.WriteLine(json);
            Console.ReadKey();
        }
复制代码

  可是,还有一个问题,若是咱们把json再反序列化为Model对象时会发生错误,由于json在反序列化为已经标记MyConverter的类Model时,MyConverter里面CanRead属性是false,反序列时是走默认反序列化,不走ReadJson()方法,json里ID属性是bool类型的,而Model里的ID属性是int类型。有三个方法能够解决:一、该模型只作序列化操做不作反序列化操做;二、新定义一个类,它的属性ID是bool类型;三、MyConverter中CanRead属性设为true,并实现ReadJson()方法。如下是第三种方法ReadJson()函数的实现:3d

复制代码
            public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
            {
                var model = new Model();
                //获取JObject对象,该对象对应着咱们要反序列化的json
                var jobj = serializer.Deserialize<JObject>(reader);
                //从JObject对象中获取键位ID的值
                var id = jobj.Value<bool>("ID");
                //根据id值判断,进行赋值操做
                if (id)
                {
                    model.ID = 1;
                }
                else
                {
                    model.ID = 0;
                }
                //最终返回的model对象就是json反序列化所获得的Model对象
                //主要,这里的model对象不必定非得是Model类型,ReadJson()方法与WriteJson()方法是同样的,能够自由操做反序列生成的对象或者序列化生成的json
                return model;
            }
复制代码

  下面附上所有代码:

  

复制代码
    class Program
    {
        static void Main(string[] args)
        {
            var model = new Model();
            model.ID = 1;
            var json = JsonConvert.SerializeObject(model);//因为ID值为1,获得json为{"ID":ture}
            var newModel = JsonConvert.DeserializeObject<Model>(json);//序列化获得的newModel对象ID值为1
        }

        [JsonConverter(typeof(MyConverter))]
        public class Model
        {
            public int ID { get; set; }
        }

        public class MyConverter : JsonConverter
        {
            //是否开启自定义反序列化,值为true时,反序列化时会走ReadJson方法,值为false时,不走ReadJson方法,而是默认的反序列化
            public override bool CanRead => true;
            //是否开启自定义序列化,值为true时,序列化时会走WriteJson方法,值为false时,不走WriteJson方法,而是默认的序列化
            public override bool CanWrite => true;

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

            public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
            {
                var model = new Model();
                //获取JObject对象,该对象对应着咱们要反序列化的json
                var jobj = serializer.Deserialize<JObject>(reader);
                //从JObject对象中获取键位ID的值
                var id = jobj.Value<bool>("ID");
                //根据id值判断,进行赋值操做
                if (id)
                {
                    model.ID = 1;
                }
                else
                {
                    model.ID = 0;
                }
                //最终返回的model对象就是json反序列化所获得的Model对象
                //主要,这里的model对象不必定非得是Model类型,ReadJson方法与WriteJson方法是同样的,能够自由操做反序列生成的对象或者序列化生成的json
                return model;
            }

            public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
            {
                //new一个JObject对象,JObject能够像操做对象来操做json
                var jobj = new JObject();
                //value参数其实是你要序列化的Model对象,因此此处直接强转
                var model = value as Model;
                if (model.ID != 1)
                {
                    //若是ID值为1,添加一个键位"ID",值为false
                    jobj.Add("ID",false);
                }
                else
                {
                    jobj.Add("ID", true);
                }
                //经过ToString()方法把JObject对象转换成json
                var jsonstr = jobj.ToString();
                //调用该方法,把json放进去,最终序列化Model对象的json就是jsonstr,由此,咱们就能自定义的序列化对象了
                writer.WriteValue(jsonstr);
            }
        }
    }
复制代码
相关文章
相关标签/搜索