2013-10-14 9 views
19

Ich möchte eine Eigenschaft mit Typname in JSON haben, wenn ich Objekte bestimmter Typen serialisieren. Ich schrieb einen Konverter:Wie Objekt zu Json mit Type Info mit Newtonsoft.Json serialisieren?

public class TypeInfoConverter : JsonConverter { 
    private readonly IEnumerable<Type> _types; 

    public TypeInfoConverter(IEnumerable<Type> types) { 
     Contract.Requires(types != null); 

     _types = types; 
    } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { 
     var jObject = JObject.FromObject(value, serializer); 
     jObject.AddFirst(new JProperty("Type", value.GetType().Name)); 
     jObject.WriteTo(writer); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { 
     return serializer.Deserialize(reader, objectType); 
    } 

    public override bool CanConvert(Type objectType) { 
     return _types.Any(t => t.IsAssignableFrom(objectType)); 
    } 
} 

Aber wenn ich versuche, Objekt zu serialisiert Ich habe eine unendlich Rekursion hier: var jObject = JObject.FromObject(value, serializer); Es ist offensichtlich, weil ich die gleiche Instanz von JsonSerializer zu benutzen, die mit dem Wandler konfiguriert wurde.

Wie kann ich verhindern, dass dieser Konverter verwendet wird, aber ich möchte andere Konverter verwenden, die für diesen Serializer konfiguriert sind?

Typen, die ich serialisieren mag:

public interface ITaskResult { 
} 

public class UserHasRejectedOffer : ITaskResult { 
    public string Message { get; set; } 
} 

public class UserHasFilledForm : ITaskResult { 
    public string FormValue1 { get; set; } 

    public string Formvalue2 { get; set; } 
} 

... 
+0

Beitrag der Code-Typen Sie zu serialisiert versuchen. – Aybe

Antwort

2

Haben Sie versucht, eine neue Instanz von JsonSerializer erstellen, dann kopieren Sie alle Wandler von den Original-Serializer mit Ausnahme des Wandlers, der die unendliche Rekursion verursacht?

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
{ 
    JsonSerializerSettings settings = new JsonSerializerSettings 
    { 
     Converters = serializer.Converters.Where(s => !(s is TypeInfoConverter)).ToList() 
     // also copy any other custom settings from the serializer you wish to pass through 
     DateFormatHandling = serializer.DateFormatHandling, 
     MissingMemberHandling = serializer.MissingMemberHandling, 
     NullValueHandling = serializer.NullValueHandling, 
     Formatting = serializer.Formatting 
    }; 
    var localSerializer = JsonSerializer.Create(settings); 

    var jObject = JObject.FromObject(value, localSerializer); 
    jObject.AddFirst(new JProperty("Type", value.GetType().Name)); 
    jObject.WriteTo(writer); 
} 
+0

Aber ich brauche noch andere JsonSerializerSettings wie DateFormatHandling, MissingMemberHandling usw. – Exta

+0

Ja, ich habe das in den Code-Kommentare oben bemerkt. Kopieren Sie einfach die Einstellungen, die Sie benötigen, vom äußeren Serializer auf den neuen Serializer. –

10
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    var converters = serializer.Converters.Where(x => !(x is TypeInfoConverter)).ToArray(); 

    var jObject = JObject.FromObject(value); 
    jObject.AddFirst(new JProperty("Type", value.GetType().Name)); 
    jObject.WriteTo(writer, converters); 
} 
+2

Dies ist eine bessere Lösung als meine. Sie können 'jObject.WriteTo (writer, converters)' einfach so tun, wie Sie es ursprünglich getan haben, anstatt jede Eigenschaft einzeln zu schreiben. –

Verwandte Themen