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);
            }
        }
    }
複製代碼
相關文章
相關標籤/搜索