2013-10-17 20 views
15

Ich habe folgende JSON Text:JSON.NET deserialisieren eine bestimmte Eigenschaft

{ 
    "PropOne": { 
     "Text": "Data" 
    } 
    "PropTwo": "Data2" 
}  

I PropOne in Typen PropOneClass ohne den Overhead von Deserialisieren alle anderen Eigenschaften für das Objekt deserialisieren möge. Kann dies mit JSON.NET geschehen?

Antwort

21
public T GetFirstInstance<T>(string propertyName, string json) 
{ 
    using (var stringReader = new StringReader(json)) 
    using (var jsonReader = new JsonTextReader(stringReader)) 
    { 
     while (jsonReader.Read()) 
     { 
      if (jsonReader.TokenType == JsonToken.PropertyName 
       && (string)jsonReader.Value == propertyName) 
      { 
       jsonReader.Read(); 

       var serializer = new JsonSerializer(); 
       return serializer.Deserialize<T>(jsonReader); 
      } 
     } 
     return default(T); 
    } 
} 

public class MyType 
{ 
    public string Text { get; set; } 
} 

public void Test() 
{ 
    string json = "{ \"PropOne\": { \"Text\": \"Data\" }, \"PropTwo\": \"Data2\" }"; 

    MyType myType = GetFirstInstance<MyType>("PropOne", json); 

    Debug.WriteLine(myType.Text); // "Data" 
} 

Dieser Ansatz vermeidet das Deserialisieren des gesamten Objekts. Aber beachten Sie, dass dies nur die Leistung verbessern wird, wenn der JSON-Wert groß ist, und die Eigenschaft, die Sie deserializing sind relativ früh in den Daten. Ansonsten solltest du einfach das ganze deserialisieren und die Teile herausziehen, die du willst, wie jcwrequests answer zeigt.

+0

Für eine bessere Wiederverwendbarkeit leicht aktualisiert. –

+1

Diese Methode ist darin enthalten, dass sie die erste Eigenschaft "PropOne" irgendwo auf jeder Ebene fängt, nicht nur in der Wurzel der Baumstruktur. Es kann behoben werden, indem Sie die Ebene verfolgen und nur den korrekten Eigenschaftsnamen auf der Stammebene akzeptieren. – hultqvist

+0

Beachten Sie, dass dies auch nützlich sein kann, wenn Sie nicht sicher sind, was die JSON-Zeichenfolge ist, die Sie dekodieren, und Sie müssen eine Eigenschaft lesen, um es herauszufinden. – starbeamrainbowlabs

1

Verwenden Sie JsonIgnore - dies wird dazu führen, dass die Eigenschaft von Json.Net sowohl für die Serialisierung als auch für die Deserialisierung vollständig ignoriert wird.

Überprüfen Sie auch diese link.

+0

Ich habe nicht ein zusammengesetztes Objekt, das sowohl 'PropOne' und' PropTwo' enthält, sondern ich habe zwei getrennte Klassen, die 'PropOne' und' PropTwo' darstellen. – Omar

+0

Serialisieren Sie auch die Objekte? – NomadTraveler

+0

Wenn du damit meine, dass ich derjenige bin, der den JSON erstellt, dann wird der JSON, den ich bekomme, von einer dritten Partei gesendet. – Omar

3
var json = "{ "PropOne": { "Text": "Data" } "PropTwo": "Data2" }"; 

JObject o = JObject.Parse(json); 
var val = o.PropTwo; 

Mit JSON Linq Provider müssen Sie das Objekt nicht in einen bekannten Typ deserialisieren.

27

Der JSON ist nicht zu groß, also nehme ich Matt Johnsons Vorschlag und deserialiere die ganze Sache. Dank jcwrequests beantworten, ich war in der Lage, diese Methode zu verwenden:

var jObject = JObject.Parse(json); 
var jToken = jObject.GetValue("PropTwo"); 
PropTwoClass value = jToken.ToObject(typeof(PropTwoClass)); 
4

Eine einfachere Lösung zu Omar's answer wäre, einen Wrapper zu haben.

class Wrapper 
{ 
    public PropOneClass PropOne; 
} 

JsonConvert.Deserialize<Wrapper>(json).PropOne 

Meine Tests fanden es etwa 30% schneller.

1

Matt's answer ist bei weitem die schnellste Lösung, obwohl es einen Fehler hat. Dies ist mein Versuch, das zu beheben. Diese Methode gibt nur eine passende Eigenschaft auf der Stammebene zurück. Es gibt immer noch einen naiven Ansatz beim Zählen von Start- und Endtoken, aber für gültige JSON wird es wahrscheinlich funktionieren.

Matt, zögern Sie nicht, dies in Ihre Antwort zu kopieren.

public T GetFirstInstance<T>(string propertyName, string json) 
{ 
    using (var stringReader = new StringReader(json)) 
    using (var jsonReader = new JsonTextReader(stringReader)) 
    { 
     int level = 0; 

     while (jsonReader.Read()) 
     { 
      switch (jsonReader.TokenType) 
      { 
       case JsonToken.PropertyName: 
        if (level != 1) 
         break; 
        if ((string)jsonReader.Value == propertyName) 
        { 
         jsonReader.Read(); 

         return (T)jsonReader.Value; 
        } 
        break; 

       case JsonToken.StartArray: 
       case JsonToken.StartConstructor: 
       case JsonToken.StartObject: 
        level++; 
        break; 

       case JsonToken.EndArray: 
       case JsonToken.EndConstructor: 
       case JsonToken.EndObject: 
        level--; 
        break; 
      } 

     } 
     return default(T); 
    } 
} 
Verwandte Themen