2016-05-10 13 views
-2

これは私が扱っているJSON文字列です。LINQ to JSON - SelectToken Error

string jsonText = "{ 
    "?xml" : { 
     "@version" : "1.0", 
     "@encoding" : "UTF-8", 
     "@standalone" : "yes" 
    }, 
    "Grid" : { 
     "DataRow" : [{ 
       "DataItem" : [{ 
         "@name" : "SYMBOL", 
         "#text" : "005930" 
        }, { 
         "@name" : "NAME", 
         "#text" : "Samsung Electronics" 
        }, { 
         "@name" : "PRICE", 
         "#text" : "1004.3" 
        }, { 
         "@name" : "VOLUME", 
         "#text" : "273.182" 
        }, { 
         "@name" : "AGG_VOLUME", 
         "#text" : "302.894" 
        } 
       ] 
      }, { 
       "DataItem" : [{ 
         "@name" : "SYMBOL", 
         "#text" : "AAPL" 
        }, { 
         "@name" : "NAME", 
         "#text" : "Apple Inc." 
        }, { 
         "@name" : "PRICE", 
         "#text" : "99" 
        }, { 
         "@name" : "VOLUME", 
         "#text" : "32936.4" 
        }, { 
         "@name" : "AGG_VOLUME", 
         "#text" : "33078.769" 
        } 
       ] 
      }, { 
       "DataItem" : [{ 
         "@name" : "SYMBOL", 
         "#text" : "MSFT" 
        }, { 
         "@name" : "NAME", 
         "#text" : "Microsoft Corporation" 
        }, { 
         "@name" : "PRICE", 
         "#text" : "42" 
        }, { 
         "@name" : "VOLUME", 
         "#text" : "103441.6" 
        }, { 
         "@name" : "AGG_VOLUME", 
         "#text" : "1324432.074" 
        } 
       ] 
      } 
     ] 
    } 
}" 
JObject feed = JObject.Parse(jsonText); 

私はSYMBOLの値のリスト、NAME、PRICE、& AGG_VOLUMEを取得しようとしています。ここに私のコードは、これまでのところです:

var covg = feed["DataItem"]["@name"].Select(f => (string)f.SelectToken("#text")); 

しかし、私は次のエラーを取得しています:私は間違って

Object reference not set to an instance of an object.

何をしているのですか?

+1

講演1:どのように小さなコードを書いてください...あなたのコードをデバッグします。 'var aaaa = feed [" DataItem "]'それから、 'aaaa'がヌルかどうかチェックします。 – Eser

答えて

1

feedは、DataItemプロパティを直接含まないルートJObjectを参照しているため、このエラーが発生しています。したがってfeed["DataItem"]はnullを返します。このnull式を逆参照しようとすると、NullReferenceExceptionがスローされます。

取得しようとしているデータは、JSONでいくつかレイヤーが下がっているため、クエリでこれを考慮する必要があります。 JSONのすべてのSYMBOL値のリストを取得するには、たとえば、あなたはこのような何かをする必要があります:

List<string> symbols = 
    feed.SelectToken("Grid.DataRow") 
     .SelectMany(jt => jt["DataItem"]) 
     .Where(jt => (string)jt["@name"] == "SYMBOL") 
     .Select(jt => (string)jt["#text"]) 
     .ToList(); 

フィドル:https://dotnetfiddle.net/jxZGZC

2

JToken.SelectTokens()JSONPath query syntaxをサポートしています。あなたが必要とクエリを実行するには、この構文を利用することができます:

  • ".."は、ワイルドカード再帰下降演算子です。したがって、feed.SelectTokens("..DataItem")は、JSON階層内のどこにあってもDataItemという名前のすべてのJSONプロパティの値を検索します。

  • "[?(@[email protected] == 'Value')]"Valueの値を持つ@nameという名前のプロパティを持つ配列のオブジェクトを照会します。

したがって、次は何が必要ありません:

var feed = JObject.Parse(jsonText); 

var query = from item in feed.SelectTokens("..DataItem") 
      select new 
      { 
       SYMBOL = (string)item.SelectToken("[?(@[email protected] == 'SYMBOL')].#text"), 
       NAME = (string)item.SelectToken("[?(@[email protected] == 'NAME')].#text"), 
       PRICE = (string)item.SelectToken("[?(@[email protected] == 'PRICE')].#text"), 
       AGG_VOLUME = (string)item.SelectToken("[?(@[email protected] == 'AGG_VOLUME')].#text") 
      }; 
var list = query.ToList();