Jazimov Jazimov - 1 month ago 18
C# Question

Linq-to-JSON SelectToken Method Confusion and Alternatives

I hope I can ask this question without provide a code sample because it's more about missing documentation and potential alternative methods/commands.

In my existing Linq-to-JSON code, I have this snippet:

var firstOrDefault = parent.AncestorsAndSelf()
.Select(p => p.SelectToken("COMPANY"))
.FirstOrDefault(k => k != null);


This code is inside a larger Linq query that iterates through all JArray and all JObject objects that descend from a root JSON object.

My question has to do with
p.SelectToken("COMPANY")
. What this appears to be doing is looking at the ancestor tree at the parent JSON and grabbing the VALUE of the first or default token it sees with a name of "COMPANY". This does exactly what I need it to do. But I have two additional requirements now:


  1. I know that any token with the name "COMPANY" always will map to a string value.

  2. I need to grab the sibling string-value JProperty objects that go along with COMPANY.



Thus, I might have a JSON snippet that looks like this:

{
"COMPANY":"Microsoft",
"LOCATION":"Seattle",
"PHONE":"800-555-1212"
"METADATA" :
{
"AA":"AA",
"BB":"BB"
}
}


In this example, I would want to use
p.SelectToken
to find the first ancestor token that contains a "COMPANY" entry--but then I need to build a List containing all sibling JProperty values, so that the List contains these JProperty elements:

"COMPANY":"Microsoft"
"LOCATION":"Seattle"
"PHONE":"800-555-1212"


Back to p.SelectToken in the lambda expression for Select. I don't know enough about Linq or the various JSON.NET methods to know which method to use other than SelectToken in order to select all of the sibling properties that sit in the same object as the selected token. I tried using a
.Where
with a lambda of
(jt => (jt.Type == JTokenType.JProperty)
and then using a
.Select
with a lambda of
(p => p.Name == "COMPANY")
, but this always produced 0 results. I am just lost. The only thing I can figure is that maybe the solution requires more than an update to the lambda expression, such as a full function with additional variables, etc.

Also, I couldn't find any good documentation at JSON.NET for SelectToken. I just see a simple example and a sentence about what it does. If there are other resources for learning about such JSON.NET Linq methods, please share.

dbc dbc
Answer

I believe this should do what you require:

    var firstOrDefault = parent
        // Walk up the hierarchy
        .AncestorsAndSelf()
        // Find an object of type JObject
        .OfType<JObject>()
        // That has a COMPANY property
        .Where(o => o["COMPANY"] != null)
        // Make a new JObject with the string properties of that JObject
        .Select(o => new JObject(o.Properties().Where(p => p.Value.Type == JTokenType.String)))
        // And return the first (lowest) one.
        .FirstOrDefault();
Comments