https://www.cnblogs.com/yijiayi/p/10051284.html
相信大家在工作中會經常遇見對json進行序列化與反序列化吧,但通常的序列化與反序列化中的json結構與c#中的類模型結構是相對應的,我們是否可以在序列化一個對象時候,讓我們json的數據結構能按照自己的意願,而不必與該對象的數據結構一樣呢?,比如說,一個對象,只有一個名為"ID"的int類型的屬性,值為1,如果序列化該對象,則能得到json:{"ID":1},但我現在希望得到的json的"ID"值是bool類型:{"ID":true}。要滿足能夠進行自定義序列化與反序列化的要求,我們可以運用json.net中的轉換器JsonConverter。
先來個簡單的例子,就上面那個,一個對象,只有一個名為"ID"的int類型的屬性,值為1,序列化該對象,如果ID值為1,則能得到json:{"ID":true},如果ID值不為1,得到json{"ID":false}。
定義類:
public class Model
{
public int ID { get; set; }
}
NuGet添加引用Newtonsoft.Json,再定義一個轉換器類MyConverter,這個類要繼承Newtonsoft.Json命名空間下的一個抽象類JsonConverter,我們先來看下這個抽象類的成員,有兩個屬性與三個抽象方法:

在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類的代碼實現:
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函數里進行測試:
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類型。有三個方法可以解決:1、該模型只做序列化操作不做反序列化操作;2、新定義一個類,它的屬性ID是bool類型;3、MyConverter中CanRead屬性設為true,並實現ReadJson()方法。以下是第三種方法ReadJson()函數的實現:
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);
}
}
}

