2013-10-17 72 views
15

我有以下JSON文本:JSON.NET反序列化特定屬性

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

我想反序列化PropOnePropOneClass類型不反序列化對象的任何其他屬性的開銷。這可以使用JSON.NET完成嗎?

回答

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" 
} 

這種方法避免了必須反序列化整個對象。但請注意,這隻會提高性能,如果json是顯着大,並且您正在反序列化的屬性在數據中相對較早。否則,你應該只是反序列化整個事情,並拉出你想要的部分,如jcwrequests答案顯示。

+0

稍微更新以獲得更好的可重用性。 –

+1

這種方法被破壞了,它會捕獲任何級別的任何地方的第一個屬性「PropOne」,而不僅僅是在樹的根部。 它可以通過跟蹤級別進行修復,只接受根級別的正確屬性名稱。 – hultqvist

+0

請注意,如果您不確定您正在解碼的JSON字符串是什麼,並且您需要讀取屬性以找出它,這也會很有用。 – starbeamrainbowlabs

1

使用JsonIgnore - 這將導致該屬性被Json.Net完全忽略,用於序列化和反序列化。

此外,請檢查此link

+0

我沒有同時包含'PropOne'和'PropTwo',而我有兩個獨立的類表示'PropOne'和'PropTwo'複合對象。 – Omar

+0

你也在序列化對象嗎? – NomadTraveler

+0

如果您認爲我是創建JSON的人,那麼不會,我得到的JSON是由第三方發送的。 – Omar

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

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

使用JSON Linq提供程序,您不需要將對象反序列化爲已知類型。

27

JSON不是太大,所以我會採取馬特約翰遜的建議並反序列化整個事情。由於jcwrequests回答,我可以用這個方法:

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

一個簡單的辦法來Omar's answer將有一個包裝。

class Wrapper 
{ 
    public PropOneClass PropOne; 
} 

JsonConvert.Deserialize<Wrapper>(json).PropOne 

我的測試發現它快了大約30%。

1

Matt's answer是迄今爲止最快的解決方案,雖然它有一個錯誤。 這是我試圖解決這個問題。 此方法將僅在根級別返回匹配屬性。 雖然對於有效的JSON,計算開始和結束標記仍然是一種天真的方法,但它可能會起作用。

馬特,隨意複製到您的答案。

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); 
    } 
}