0

The following is my json string:

string json = @"{
    '?xml' : {
        '@version' : '1.0',
        '@encoding' : 'UTF-8'
    },
    'DataFeed' : {
        '@FeedName' : 'AdminData',
        'Issuer' : {
            'id' : '95',
            'name' : 'Apple',
            'symbol' : 'AAPL'
        }
    }
}";

When I try to do the following LINQ query:

JObject feed = JObject.Parse(json);

var compInfo = feed["DataFeed"]["Issuer"]
    .Select(c => c["name"]);

I get the following error:

`Cannot access child value on Newtonsoft.Json.Linq.JProperty.`

However, the following works fine:

var test1 = feed["DataFeed"]["Issuer"]["name"];

Any idea why I can't use LINQ on this json string?

inquisitive_one
  • 1,465
  • 7
  • 32
  • 56
  • 1
    What would you expect using `Select` to give you? You're iterating over the `JObject` of `Issuer`... – Jon Skeet Apr 05 '16 at 19:51
  • I should get `Apple`. How should i be doing this? – inquisitive_one Apr 05 '16 at 19:54
  • `Issuer` is an inner `JObject`. You can't use Linq from a `JObject`, check this [link](http://www.newtonsoft.com/json/help/html/QueryingLINQtoJSON.htm) for more details – ocuenca Apr 05 '16 at 20:00
  • 1
    To get `Apple` you just use `string x = (string) feed["DataFeed"]["Issuer"]["name"];` – Jon Skeet Apr 05 '16 at 20:01
  • 1
    Or [`var x = (string)feed.SelectToken("DataFeed.Issuer.name")`](http://www.newtonsoft.com/json/help/html/QueryJsonSelectToken.htm) which won't throw a null reference exception if an intermediate object is missing. – dbc Apr 05 '16 at 20:46

2 Answers2

1

Think about what your JSON is. You're selecting from a dictionary so the result in the LINQ is the property. You're trying to then access "name" on a property which doesn't make sense which gives you the error.

You already have the working code:

var test1 = feed["DataFeed"]["Issuer"]["name"];
James Newton-King
  • 48,174
  • 24
  • 109
  • 130
  • 1
    Since the man himself is here, any comments about my solution or how can I improve it? Also, thanks for Json.net. – Nasreddine Apr 06 '16 at 12:09
0

You can get the value you want using two methods:

Method 1:

First you need a cast from JToken to a JObject since the value of 'Issuer' is an object:

var compInfo = (JObject)feed["DataFeed"]["Issuer"];

Then loop through all the properties to find the one with the name "Name" then get its value as a string:

var str = compInfo.Properties().First(x => x.Name == "name").ToObject<string>();
// str will contain the value 'Apple'.

Method 2:

You can also deserialize the JSON into an object that is easier to handle. To do that first you'll need to create a .net object "equivalent" of your JSON . You can use Visual Studio to generate these for you from the Edit menu -> Paste Special -> Paste JSON as classes or use a website like JsonUtils.com

public class Xml
{

    [JsonProperty("@version")]
    public string Version { get; set; }

    [JsonProperty("@encoding")]
    public string Encoding { get; set; }
}

public class Issuer
{

    [JsonProperty("id")]
    public string Id { get; set; }

    [JsonProperty("name")]
    public string Name { get; set; }

    [JsonProperty("symbol")]
    public string Symbol { get; set; }
}

public class DataFeed
{

    [JsonProperty("@FeedName")]
    public string FeedName { get; set; }

    [JsonProperty("Issuer")]
    public Issuer Issuer { get; set; }
}

public class RootJsonObject
{

    [JsonProperty("?xml")]
    public Xml Xml { get; set; }

    [JsonProperty("DataFeed")]
    public DataFeed DataFeed { get; set; }
}

Then all you have to do to get the Issuer name is this:

var feed = JsonConvert.DeserializeObject<RootJsonObject>(json);
var issuer = feed.DataFeed.Issuer.Name;
Nasreddine
  • 36,610
  • 17
  • 75
  • 94