4
votes

Given the following JSON:

{
  "Data": {
    "SPECIAL": "QQ01",
    "AA": "QQ",
    "BB": "QQ",
    "Data": [
      {
        "SPECIAL": "QQ02",
        "AA": "QQ",
        "BB": "QQ",
        "CC": "QQ",
        "Data": [
          {
            "SPECIAL": "QQ03",
            "AA": "QQ",
            "CC": "QQ",
            "Data": [
              {
                "SPECIAL": "QQ04",
                "AA": "QQ",
                "CC": "QQ",
                "Data": [
                  {
                    "SPECIAL": "QQ05",
                    "AA": "QQ",
                    "CC": "QQ",
                    "Data": [
                      {
                        "SPECIAL": "QQ06",
                        "AA": "QQ",
                        "CC": "QQ"
                      }
                    ]
                  },
                  {
                    "SPECIAL": "QQ07",
                    "AA": "QQ",
                    "CC": "QQ",
                    "DD": "QQ",
                    "Data": [
                      {
                        "SPECIAL": "QQ08",
                        "AA": "QQ",
                        "CC": "QQ",
                        "Data": [
                          {
                            "SPECIAL": "QQ09",
                            "AA": "QQ",
                            "BB": "QQ",
                            "CC": "QQ"
                          }
                        ]
                      }
                    ]
                  }
                ]
              }
            ]
          }
        ]
      }
    ]
  }
}

I thought I understood that a JSON property is simply a name/value pair, where the name is a string and the value can be a string, a JArray, or an JObject. If I am correct, my sample JSON above opens with a Data JObject that contains 3 sibling properties: SPECIAL, AA, and BB.

Observe that the next Data entry is a JArray. The array's first element contains an object that has 4 properties: SPECIAL, AA, BB, and CC.

QUESTION: How would I issue a Linq query to return the sibling properties for SPECIAL equal to QQ01? The return value should be a List of JProperty containing only: SPECIAL:QQ01, AA:QQ, and BB:QQ. Notice that these properties are in a JObject.

The same query would need to work if I want the 4 sibling properties for SPECIAL equal to QQ02. In that case, the return value would be a List of JProperty containing only: SPECIAL:QQ02, AA:QQ, BB:QQ, and CC:QQ. Notice that these properties are in a JObject that's in a JArray.

Oh, if there is more than one entry with SPECIAL equal to QQ01 or, in the second case, with SPECIAL equal to QQ02--then I would want only the first.

Thank you.

1

1 Answers

6
votes

Here's how I would do it:

JObject jo = JObject.Parse(json);

var props = jo.Descendants()
    .OfType<JProperty>()
    .Where(p => p.Name == "SPECIAL" && (string)p.Value == "QQ01")
    .Take(1)
    .Select(p => p.Parent)
    .SelectMany(o => o.Children<JProperty>())
    .Where(p => p.Value.Type == JTokenType.String)
    .ToList();

foreach (JProperty prop in props)
{
    Console.WriteLine(prop.Name + ": " + prop.Value);
}

Fiddle: https://dotnetfiddle.net/nvIXkO