定制json序列化
阿新 • • 發佈:2018-07-27
類成員 lin foreach set test roo rto trac ring
最近有人問我怎麽定制一個json序列化,使序列化的時候只寫出聲明的父類成員,而不要把實際子類的成員寫出來。當然,序列化用的是大家用的最多的json.net。
簡單的說,這是個契約怎麽解析的問題,json.net選擇使用實際類型自然是有多方面的考量,畢竟申明類型可以是抽象類或接口等。廢話不說了,直接上代碼(僅用於示例,要用於生產的話需要處理各種邊緣情況)。
類型關系
public class RootObj { public A A { get; set; } } public class A { public string X { get; set; } } public class B : A { public string Y { get; set; } }
實例和序列化
在什麽都不改的情況下,輸出是:var r = new RootObj { A = new B { X = "x", Y = "y" } }; Console.WriteLine(JsonConvert.SerializeObject(r));
{"A":{"Y":"y","X":"x"}}
而期望值是:
{"A":{"X":"x"}}
我們期望只輸出A的成員。寫自己的JsonConverter:
public class JC<T> : JsonConverter { public override bool CanConvert(Type objectType) => throw new NotImplementedException(); 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) { writer.WriteStartObject(); var contract = (JsonObjectContract)serializer.ContractResolver.ResolveContract(typeof(T)); foreach (var prop in contract.Properties) { writer.WritePropertyName(prop.PropertyName); serializer.Serialize(writer, prop.ValueProvider.GetValue(value)); } writer.WriteEndObject(); } }
標記我們的類型
public class RootObj { [JsonConverter(typeof(JC<A>))] public A A { get; set; } }
Run! 然後就可以發現結果和我們期待的一樣了:)
源代碼傳輸門
定制json序列化