2014-06-22 83 views

回答

12

簡單地說,existingValue參數爲您提供了最終將被從ReadJson方法返回的值替換的對象的現有值或默認值。這使得ReadJson方法有機會在確定要返回的內容時評估現有值。例如,該方法可以決定保留默認值,或者在某種程度上將其與來自閱讀器的反序列化值相結合(如果需要)。

考慮下面的例子。該轉換器將從JSON中反序列化一個整數值,並返回該值的總和以及被反序列化的字段的現有值。

class AdditiveIntConverter : JsonConverter 
{ 
    public override bool CanConvert(Type objectType) 
    { 
     return (objectType == typeof(int)); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     JToken token = JToken.Load(reader); 
     return (int)existingValue + token.ToObject<int>(); 
    } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     throw new NotImplementedException(); 
    } 
} 

現在讓我們說我們有一個類Foo有兩個int性質,Value1Value2,它們都使用該轉換器。 Value1在構造函數中分配了默認值42,而Value2的默認值爲零。

class Foo 
{ 
    [JsonConverter(typeof(AdditiveIntConverter))] 
    public int Value1 { get; set; } 

    [JsonConverter(typeof(AdditiveIntConverter))] 
    public int Value2 { get; set; } 

    public Foo() 
    { 
     Value1 = 42; 
    } 
} 

如果我們反序列化一些數據到這個類...

class Program 
{ 
    static void Main(string[] args) 
    { 
     string json = @"{ ""Value1"" : 18, ""Value2"" : 33 }"; 

     Foo foo = JsonConvert.DeserializeObject<Foo>(json); 
     Console.WriteLine("Value1: " + foo.Value1); 
     Console.WriteLine("Value2: " + foo.Value2); 
    } 
}  

...我們得到以下結果:

Value1: 60 
Value2: 33 

當然,這只是一個人爲的例子。實際上,在實現JsonConverter時沒有太多需要使用existingValue參數,並且大多數時候它的值將爲null或零。你可以放心地忽略它。

2

existingValue是一個可選值(檢查爲空),可以通過其他方法或基方法部分反序列化。這通常爲空,但在設置具有JsonConverter的屬性時可能不爲空。

我還沒有看到任何使用此值的ReadJson實現(但這並不意味着沒有任何)。

4

我相信這個主要用例是爲了「填充」其值是可變的但本身不可寫的現有屬性。例如:

public class A { 
    private readonly List<int> b = new List<int> { 1 }; 
    public List<int> B { get { return this.b; } } 
} 

JsonConvert.DeserializeObject<A>("{ B: [2] }").Dump(); // B has both 1 and 2! 

現在,讓我們說,而不是稱爲B,我們有一個自定義類型的只讀屬性列表:

// try this code in LinqPad! 
void Main() 
{ 
    JsonConvert.DeserializeObject<A>("{ C: { Y: 5 } }").Dump(); 
} 

// Define other methods and classes here 
public class A { 
    private readonly C c = new C { X = 1 }; 
    public C C { get { return this.c; } } 
} 

[JsonConverter(typeof(CJsonConverter))] 
public class C { 
    public int X { get; set; } 
    public int Y { get; set; } 
} 

public class CJsonConverter : JsonConverter { 
    public override bool CanConvert(Type objectType) 
    { 
     return objectType == typeof(C); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     // VERSION 1: don't use existingValue 
     //var value = new C(); 
     // VERSION 2: use existingValue 
     var value = (C)existingValue ?? new C(); 

     // populate value 
     var dict = serializer.Deserialize<Dictionary<string, int>>(reader); 
     if (dict.ContainsKey("X")) { value.X = dict["X"]; } 
     if (dict.ContainsKey("Y")) { value.Y = dict["Y"]; } 
     return value; 
    } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     throw new NotImplementedException(); 
    } 
} 

注意,代碼顯示2種方式來寫轉換器。一個使用現有值,另一個不使用。如果我們使用現有值,我們將"{ C: { Y: 5 } }"反序列化爲:{ C: { X: 1, Y:5 } },從而保留X = 1的缺省值並填充只讀屬性C.另一方面,如果我們不使用現有值並始終讓我們的轉換器創建一個新的C,那麼我們根本無法填充只讀C屬性。

相關問題