-2

This is the JSON string that I am working with.

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

I'm trying to get a list of values for SYMBOL, NAME, PRICE, & AGG_VOLUME. Here's my code so far:

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

But I'm getting the following error:

Object reference not set to an instance of an object.

What am I doing wrong?

inquisitive_one
  • 1,465
  • 7
  • 32
  • 56
  • 1
    Lecture 1: how to debug your code... Write smaller codes. `var aaaa = feed["DataItem"]` Then check if `aaaa` is null etc....... – Eser May 10 '16 at 20:33

2 Answers2

2

JToken.SelectTokens() supports JSONPath query syntax. You can make use of this syntax to perform the query you require:

  • ".." is the wildcard recursive descent operator. Thus feed.SelectTokens("..DataItem") finds the values of all JSON properties named DataItem no matter where they are in the JSON hierarchy.

  • "[?(@.@name == 'Value')]" queries for objects in an array with a property named @name with value Value.

Thus, the following does what you need:

var feed = JObject.Parse(jsonText);

var query = from item in feed.SelectTokens("..DataItem")
            select new
            {
                SYMBOL = (string)item.SelectToken("[?(@.@name == 'SYMBOL')].#text"),
                NAME = (string)item.SelectToken("[?(@.@name == 'NAME')].#text"),
                PRICE = (string)item.SelectToken("[?(@.@name == 'PRICE')].#text"),
                AGG_VOLUME = (string)item.SelectToken("[?(@.@name == 'AGG_VOLUME')].#text")
            };
var list = query.ToList();
dbc
  • 104,963
  • 20
  • 228
  • 340
1

You are getting this error because feed refers to the root JObject which does not directly contain a DataItem property. Thus feed["DataItem"] returns null. When you then try to dereference this null expression it throws a NullReferenceException.

The data you are trying to get is several layers down in the JSON, so your query has to account for this. To get a list of all SYMBOL values in the JSON, for example, you would need to do something like this:

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

Fiddle: https://dotnetfiddle.net/jxZGZC

Brian Rogers
  • 125,747
  • 31
  • 299
  • 300