10

I am working at parsing a json http response with Json.NET and have working code, but am pretty sure I am going about it in an overly complicated way. My question is if there is a more direct way to get a child jToken by path and/or de-serialize it without foreaching every level.

I tried this approach but it returns null:

  JObject jObj = JObject.Parse( text );
  JToken myVal;
  jObj.TryGetValue( "response.docs", out myVal );

Here is my working overly complicated code, including de-serialization:

  JObject jObj = JObject.Parse( text );

  foreach( var kv in jObj ) {
    if( kv.Key == "response" ) {
      foreach( JToken jt in kv.Value ) {
        if( jt.Path == "response.docs" ) {
          JEnumerable<JToken> children = jt.Children();
          foreach( JToken t in children ) {       
            //THIS WORKS BUT IS NOT ELEGANT 
            Solr_User[] su = t.ToObject<Solr_User[]>();
          }
        }
      }
    }
  }

And here is the JSON raw response just for reference:

{
  "responseHeader":{
    "status":0,
    "QTime":0,
    "params":{
      "q":"*:*",
      "indent":"on",
      "wt":"json"}},
  "response":{"numFound":4,"start":0,"docs":[
      {
        "id":3,
        "first_name":"Bob",
        "_version_":"1558902640594649088"},
      {
        "id":4,
        "first_name":"Sam",
        "_version_":"1558902640613523456"},
      {
        "id":2,
        "first_name":"Fred",
        "_version_":"1558902640613523457"},
      {
        "id":1,
        "first_name":"Max",
        "_version_":"1558902640613523458"}]
  }}
0

1 Answer 1

16

You can use SelectToken() to select a token from deep within the LINQ-to-JSON hierarchy for deserialization. In two lines:

var token = jObj.SelectToken("response.docs");
var su = token == null ? null : token.ToObject<Solr_User []>();

Or in one line, by conditionally deserializing a null JToken when the selected token is missing:

var su = (jObj.SelectToken("response.docs") ?? JValue.CreateNull()).ToObject<Solr_User []>();

Sample fiddle.

In c# 6 or later it's even easier to deserialize a nested token in one line using the null conditional operator:

var su = jObj.SelectToken("response.docs")?.ToObject<Solr_User []>();

Or even

var su = jObj?["response"]?["docs"]?.ToObject<Solr_User []>();

Note that SelectTokens() is slightly more forgiving than the JToken index operator, as SelectTokens() will return null for a query of the wrong type (e.g. if the value of "response" were a string literal not a nested object) while the index operator will throw an exception.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.