CanConvert
wird nicht aufgerufen, wenn Sie etwas mit [JsonConverter]
markieren. Wenn Sie das Attribut verwenden, geht Json.Net davon aus, dass Sie den richtigen Konverter bereitgestellt haben, so dass es sich nicht um die Überprüfung der CanConvert
handelt. Wenn Sie das Attribut entfernen, wird es aufgerufen, indem Sie die Konverterinstanz an die Einstellungen übergeben. Was Sie sehen, ist Json.Net testet Ihren Konverter für alle anderen Eigenschaftstypen.
EDIT
ich schnell fiddle zusammen zu zeigen, was ich meine (Code auch unten auf Vollständigkeit wiedergegeben wird).
ohne Änderungen das Programm, CanConvert()
auf der FooConverter
für alle Arten aufgerufen wird außerFoo
, aber es wandelt noch Foo
richtig.
Wenn Sie das [JsonConverter]
Attribut auf dem Wrapper.Foo
Eigenschaft kommentieren, können Sie sehen, dass CanConvert()
wird nun für Typ Foo
aufgrund der FooConverter
im JsonSerializerSettings
enthalten sind aufgerufen.
Wenn Sie stattdessen die Zeile in Main
kommentieren, wo die FooConverter
die Einstellungen hinzugefügt wird, dann wird CanConvert
nie für jede Art genannt, noch Foo
noch korrekt aufgrund des [JsonConverter]
auf die Foo
Eigenschaft im Wrapper
angewandt Attribute umgewandelt wird Klasse.
Also hier ist es, dass es zwei Mechanismen gibt, um anzuzeigen, ob ein Konverter verwendet werden sollte, und Sie beide nicht benötigen. Sie können ein Attribut anwenden und Json.Net mitteilen, dass ein bestimmter Konverter für eine bestimmte Eigenschaft (oder Klasse) verwendet werden soll und der Konverter nicht zuerst abgefragt werden muss. Alternativ können Sie den Konverter zu den Einstellungen hinzufügen. In diesem Fall muss Json.Net jeden Konverter fragen, ob er den jeweiligen Typ verarbeiten kann. Ersteres ist etwas effizienter, während letzteres in Situationen nützlich ist, in denen Sie nicht den Quellcode für die Klasse besitzen, die Sie konvertieren möchten. Hoffe, das macht Sinn.
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
public class Program
{
public static void Main()
{
JsonSerializerSettings settings = new JsonSerializerSettings();
// Comment out the following line and CanConvert() never gets called on
// FooConverter for any type yet the FooConverter is still working due
// to the JsonConverter attribute applied to Wrapper.Foo
settings.Converters.Add(new FooConverter());
settings.Converters.Add(new BarConverter());
settings.Formatting = Formatting.Indented;
Wrapper w = new Wrapper
{
Foo = new Foo
{
A = "bada",
B = "boom",
},
Bar = new Bar
{
C = "bada",
D = "bing"
}
};
string json = JsonConvert.SerializeObject(w, settings);
Console.WriteLine(json);
}
class Wrapper
{
// Comment out this attribute and CanConvert will be called on FooConverter
// for type Foo due to the fact that the FooConverter has been added to the
// JsonSerializerSettings
[JsonConverter(typeof(FooConverter))]
public Foo Foo { get; set; }
public Bar Bar { get; set; }
}
class Foo
{
public string A { get; set; }
public string B { get; set; }
}
class Bar
{
public string C { get; set; }
public string D { get; set; }
}
class FooConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
bool result = typeof(Foo).IsAssignableFrom(objectType);
Console.WriteLine("FooConverter CanConvert() called for type " +
objectType.Name + " (result = " + result + ")");
return result;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var foo = (Foo) value;
JObject jo = new JObject();
jo.Add("AplusB", new JValue(foo.A + " " + foo.B));
jo.WriteTo(writer);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
class BarConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
bool result = typeof(Bar).IsAssignableFrom(objectType);
Console.WriteLine("BarConverter CanConvert() called for type " +
objectType.Name + " (result = " + result + ")");
return result;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var bar = (Bar) value;
JObject jo = new JObject();
jo.Add("CplusD", new JValue(bar.C + " " + bar.D));
jo.WriteTo(writer);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
}
Klassenmodifikator ist öffentlich? – codebased
Ja, sowohl die Entität als auch der Konverter sind öffentlich. – ilivewithian