I suppose this is another entry in my series of questions, but I\'m stuck again. This time, I\'m having trouble working with a JArray of JObjects and determining the Propert
This produces the output you require:
var root = (JContainer)JToken.Parse(json);
var query = root.Descendants()
.Where(jt => (jt.Type == JTokenType.Object) || (jt.Type == JTokenType.Array))
.Select(jo =>
{
if (jo is JObject)
{
if (jo.Parent != null && jo.Parent.Type == JTokenType.Array)
return null;
// No help needed in this section
// populate and return a JObject for the List<JObject> result
// next line appears for compilation purposes only--I actually want a populated JObject to be returned
return new JObject();
}
if (jo is JArray)
{
var items = jo.Children<JObject>().SelectMany(o => o.Properties()).Where(p => p.Value.Type == JTokenType.String);
return new JObject(items);
}
return null;
})
.Where(jo => jo != null)
.ToList();
Here I use SelectMany() to flatten the nested enumeration of properties of the enumeration of child objects of jo
to a single enumeration of all properties of child objects. o => o.Properties()
is a lambda expression mapping the JObject o
to its collection of properties, and p => p.Value.Type == JTokenType.String
is another lambda mapping a property p
(generated by the previous SelectMany
clause) to a true/false value indicating whether the property has a string value. Both o
and p
are lambda input parameters that are implicitly typed.
Also, in the // No help needed in this section
section, objects whose parents are arrays are skipped, since they will get collected by the (jo is JArray)
clause.
Note that if different children of the jo
array happen to have identical property names, the JObject
constructor may throw a duplicated key exception.
Forked fiddle.