2

So I have a JSON object that looks like this

{
  "someOtherData": "notImportant",
  "outerlist": [
    {
      "somedata": 1504461600,
      "innerList": [
        {
          "data1": 801,
          "data2": "blah",
          "innerDataNeeded": "the inner list data needed"
        }
      ],
      "outerDataNeeded": "outer Data Needed"
    }
  ]
}

I was trying to write a linq query to return both the innerDataNeeded and the outerDataNeeded

So I wrote two to get both but I'm not sure how to connect them together and get the desired result with one query.

current code is like so

var listOfInnerData = from listItem in jsonObject["outerList"] from innerJsonList in listItem["innerList"] select (string) innerJsonList["innerDataNeeded"];
var listOfOuterData = from listItem in jsonObject["outerList"] select (string)listItem["outerDataNeeded"];
1
  • Convert your json to concrete classes, so you can work on it easier. json2csharp.com Commented Sep 3, 2017 at 18:30

1 Answer 1

1

You have a few options to extract the innerDataNeeded and outerDataNeeded, joined together in groups, using LINQ-to-JSON.

Firstly, you could use nested from statements to perform a SelectMany() on the inner list to generate a single, flat list of joined pairs:

var query = from outerItem in jsonObject.SelectTokens("outerlist[*]")
            let outerData = outerItem["outerDataNeeded"]
            from innerData in outerItem.SelectTokens("innerList[*].innerDataNeeded")
            select new { OuterData = (string)outerData, InnerData = (string)innerData };

var listOfData = query.ToList();

Resulting in

[
  {
    "OuterData": "outer Data Needed",
    "InnerData": "the inner list data needed"
  }
]

Secondly, if there is a possibility that the innerList array might be missing or empty and you still want to get the corresponding outer data values, you can sub in a default value using DefaultIfEmpty():

var query = from outerItem in jsonObject.SelectTokens("outerlist[*]")
            let outerData = outerItem["outerDataNeeded"]
            from innerData in outerItem.SelectTokens("innerList[*].innerDataNeeded").DefaultIfEmpty(JValue.CreateNull())
            select new { OuterData = (string)outerData, InnerData = (string)innerData };

var listOfData = query.ToList();

Finally, if you would prefer your list of results to be structured as outer an inner collections, you can use a nested LINQ query as follows:

var query = from outerItem in jsonObject.SelectTokens("outerlist[*]")
            select new 
            {
                OuterData = (string)outerItem["outerDataNeeded"], 
                InnerData = outerItem.SelectTokens("innerList[*].innerDataNeeded").Select(i => i.ToString()).ToArray() 
            };

var listOfData = query.ToList();

Which results in:

[
  {
    "OuterData": "outer Data Needed",
    "InnerData": [
      "the inner list data needed"
    ]
  }
]

Sample fiddle showing these three options.

Notes -

  • The method SelectTokens() enables selection of multiple tokens using JSONPath query syntax. In this syntax, the [*] operator is a wildcard that matches all array members. Using SelectTokens() avoids the need for nested from/select queries at each level of the JToken hierarchy.

  • If certain properties are missing, SelectTokens() will simply not enumerate over anything, whereas nested from/select will throw null reference exceptions unless null is checked for and skipped.

  • Pasting your JSON to http://json2csharp.com/ or using Paste JSON As Classes to generate concrete types for your JSON, then deserializing to those types and querying the result, is another option to consider.

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.