2014-06-22 39 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属性。

相关问题