定製json序列化

最近有人問我怎麼定製一個json序列化,使序列化的時候只寫出聲明的父類成員,而不要把實際子類的成員寫出來。固然,序列化用的是你們用的最多的json.net。git

簡單的說,這是個契約怎麼解析的問題,json.net選擇使用實際類型天然是有多方面的考量,畢竟申明類型能夠是抽象類或接口等。廢話不說了,直接上代碼(僅用於示例,要用於生產的話須要處理各類邊緣狀況)。github

  1. 類型關係json

    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; }
    }
  2. 實例和序列化ide

    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的成員。
  3. 寫本身的JsonConverter:.net

    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();
        }
    }
  4. 標記咱們的類型code

    public class RootObj
    {
        [JsonConverter(typeof(JC<A>))]
        public A A { get; set; }
    }
  5. Run! 而後就能夠發現結果和咱們期待的同樣了:)接口

源代碼傳輸門get

相關文章
相關標籤/搜索