簡體   English   中英

如何基於父類類型有選擇地從序列化中排除屬性

[英]How to selectively exclude a property from serialization based on the parent class type

我正在使用Newtonsoft.JSON庫來序列化多個對象。 在某些情況下,我不想序列化屬性,因此我使用了ShouldSerialize前綴,該前綴在大多數情況下已大獲成功。 在一種情況下,如果屬性屬於特定類,我只想序列化它。

我已經嘗試過使用堆棧跟蹤,但是它只告訴我JSON對象正在調用ShouldSerialize方法。 我不需要知道應該調用ShouldSerialize的信息,我不需要知道ShouldSerialize屬於哪個父類,例如Parent.Child.ShouldSerialize。

在下面的代碼示例中,如何在使用JSON對象時確定父類名稱是什么?

class Foo
{
    public SharedClass SomeProperty
    {
           get;
           set;
    }
}

class Bar
{
    public SharedClass SomeProperty
    {
           get;
           set;
    }
}

class SharedClass
{
    public string SomeValue
    {
           get;
           set;
    }

    public bool ShouldSerializeSomeValue
    {
           //pseudo logic
           return ClassName == "Foo";
    }
}

正如Lasse Karlsen在評論中指出的那樣,如果您的SharedClass沒有對其父級的引用,則ShouldSerializeSomeValue()中的ShouldSerializeSomeValue()方法將無法知道父級是什么。

但是,如果使用的是Json.Net 6.0 Release 6或更高版本,則可以通過使用自定義JsonConverter作為有選擇地從共享類中忽略屬性的方法(而不是使用ShouldSerialize()方法)來解決此問題,然后放置適當的父類內SharedClass屬性上的[JsonConverter]屬性,指示該實例應忽略哪些屬性。

這是更新后的示例類定義的外觀。 你會發現我已經標志着SharedClass的實例Foo指明應該使用稱為自定義轉換器OmitPropertiesConverter省略SomeValue財產。 Bar上的SharedClass實例不使用轉換器,因此該實例將被正常序列化。

class Foo
{
    [JsonConverter(typeof(OmitPropertiesConverter), "SomeValue")]
    public SharedClass Shared { get; set; }
}

class Bar
{
    public SharedClass Shared { get; set; }
}

class SharedClass
{
    public string SomeValue { get; set; }
    public string SomeOtherValue { get; set; }
}

以下是OmitPropertiesConverter的代碼。 它的構造函數接受propsToOmit字符串,該字符串是一個逗號分隔的屬性名稱列表,該屬性名稱將從序列化中排除。 這將拆分為一個數組,以供以后在WriteJson方法中使用。 WriteJson方法以SharedClass值,將其轉換為JObject ,然后以編程除去它們是在屬性propsToOmit陣列寫入之前JObjectJsonWriter

class OmitPropertiesConverter : JsonConverter
{
    string[] propsToOmit;

    public OmitPropertiesConverter(string propsToOmit)
    {
        this.propsToOmit = propsToOmit.Split(new char[] {','},
                                             StringSplitOptions.RemoveEmptyEntries);
    }

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

    public override void WriteJson(JsonWriter writer, object value, 
                                   JsonSerializer serializer)
    {
        JObject jo = JObject.FromObject(value, serializer);

        // Note: ToList() is needed here to prevent "collection was modified" error
        foreach (JProperty prop in jo.Properties()
                                     .Where(p => propsToOmit.Contains(p.Name))
                                     .ToList())
        {
            prop.Remove();
        }

        jo.WriteTo(writer);
    }

    public override bool CanRead
    {
        get { return false; }
    }

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

這是一個簡單的演示程序,顯示了運行中的轉換器:

class Program
{
    static void Main(string[] args)
    {
        var root = new
        {
            Foo = new Foo
            {
                Shared = new SharedClass
                {
                    SomeValue = "foo1",
                    SomeOtherValue = "foo2"
                }
            },
            Bar = new Bar
            {
                Shared = new SharedClass
                {
                    SomeValue = "bar1",
                    SomeOtherValue = "bar2"
                }
            }
        };

        string json = JsonConvert.SerializeObject(root, Formatting.Indented);
        Console.WriteLine(json);
    }
}

這是上述演示的輸出。 您會注意到,輸出中未包含FooSharedClass實例上的SomeValue屬性,但它包含在Bar內的實例上。

{
  "Foo": {
    "Shared": {
      "SomeOtherValue": "foo2"
    }
  },
  "Bar": {
    "Shared": {
      "SomeValue": "bar1",
      "SomeOtherValue": "bar2"
    }
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM