2017-08-11 5 views
1

Ich habe eine JSON-Nachricht zum Deserialisieren mit einer Zeichenfolge-Eigenschaft, die den JSON eines anderen Objekts enthält. Ich habe die folgenden KlassenJSON.NET Deserialize JSON-Objekt als Eigenschaft gespeichert

public class Envelope 
{ 
    public string Type { get; set; } 
    public Message InnerMessage { get; set; } 
} 

public class Message 
{ 
    public string From { get; set; } 
    public string To { get; set; } 
    public string Body { get; set; } 
} 

die JSON Nachricht Ich erhalte in diesem Format ist:

{ 
    Type : "send", 
    InnerMessage : "{ From: \"sender\", To: \"receiver\", Body: \"test\" }" 
} 

beachten Sie, dass InnerMessage die Serialisierung der Message Klasse enthält, nicht die JSON der Klasse.

Wenn ich den Typ der InnerMessage-Eigenschaft zu Message beibehalten, schlägt die Standard-JSON.NET-Deserialisierung fehl.

Wenn ich ändern, um die InnerMessage zu string, die Serialisierung funktioniert, aber nachdem ich wieder den Inhalt InnerMessage zu Message Klasse deserialisiert müssen:

Envelope envelope = JsonConvert.DeserializeObject<Envelope>(jsonMessage); 
Message innerMessage = JsonConvert.DeserializeObject<Envelope>(envelope.InnerMessage); 

Es besteht eine gewisse Möglichkeit, die InnerMessage Eigenschaft Envelope zu Message zu halten und JSON.NET anweisen, den zu deserialisierenden String-Wert automatisch zu behandeln?

+0

Wie werden Sie Ihr Objekt Serialisierung? Wenn ich 'JsonConvert.SerializeObject (envelope)' verwende, erhalte ich eine andere Json-Ausgabe als du. –

+0

Ich bekomme die JSON von einem Webservice, ich muss es nur zu den Klassen deserialize –

+0

Gotcha, sieht aus wie @SirRufo hat die Antwort Ihre Suche nach –

Antwort

2

Sie benötigen eine benutzerdefinierte JsonConverter

class StringTypeConverter : Newtonsoft.Json.JsonConverter 
{ 
    public override bool CanRead => true; 
    public override bool CanWrite => true; 

    public override bool CanConvert(Type objectType) 
    { 
     return true; 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     string json = (string)reader.Value; 
     var result = JsonConvert.DeserializeObject(json, objectType); 
     return result; 
    } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     var json = JsonConvert.SerializeObject(value); 
     serializer.Serialize(writer, json); 
    } 
} 

und JsonConverterAttribute zum InnerMessage Eigenschaft hinzufügen

public class Envelope 
{ 
    public string Type { get; set; } 
    [Newtonsoft.Json.JsonConverter(typeof(StringTypeConverter))] 
    public Message InnerMessage { get; set; } 
} 

public class Message 
{ 
    public string From { get; set; } 
    public string To { get; set; } 
    public string Body { get; set; } 
} 

und jetzt Sie serialisieren/deserialisieren die Envelope Klasse mit

var envelope = JsonConvert.DeserializeObject<Envelope>(jsonMessage); 
+0

gelten Dank, Ihre Lösung sieht sauberer als die andere, morgen werde ich es testen –

+0

Ihre Lösung funktioniert perfekt, noch einmal vielen Dank –

2

Sie können dies mit einem benutzerdefinierten Konverter tun. Zum Beispiel:

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

    public override object ReadJson(JsonReader reader, Type objectType, 
     object existingValue, JsonSerializer serializer) 
    { 
     var envelope = JObject.Load(reader); 

     var type = envelope["Type"].ToString(); 
     var message = JsonConvert.DeserializeObject<Message>(
      envelope["InnerMessage"].ToString()); 

     return new Envelope 
     { 
      Type = type, 
      InnerMessage = message 
     }; 
    } 

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

    public override bool CanConvert(Type objectType) 
    { 
     return true; 
    } 
} 

Und es wie folgt verwenden:

Envelope envelope = JsonConvert.DeserializeObject<Envelope>(
    jsonMessage, new EnvelopeConverter()); 
+0

danke für Ihre Antwort, aber persönlich bevorzuge ich die von Sir Rufo wie ich kann auf die spezifische Eigenschaft und nicht auf die Klasse –

Verwandte Themen