0

I thought this question might be ill-formed, so I created a "sister" question that's far more to-the-point, which specific output cited. Please see to: Querying JSON Nested Arrays with Linq, JSON.NET, C# If that question gets answered before this one, I'll try to answer this one myself using the information from the other question... :) Thanks!

In a previous question (Picking Out Simple Properties from Hierarchical JSON), I asked how to pick up simple properties from hierarchical JSON. The answer there [pasted as a Linq query at the end of this post] is extremently useful (and, since posting that, I've studied quite a bit about Linq and JSON.NET). So I'm not using this forum because I'm lazy--I use it when I'm really stuck and can't seem to find the answers in the books I have access to.

I'm stumped on how to continue with the example provided by my previous question. This question builds on the previous one, so here (as succinctly as I could express) is what I'd love to learn how to do in a single Linq query.

To recap: I'm working with dynamic JSON like this (it is more complex than the JSON presented in my earlier Part I question because it contains arrays):

{
    "Branch1": {
        "Prop1A": "1A",
        "Prop1B": "1B",
        "Prop1C": "1C",
        "Branch2": {
            "Prop2A": "2A",
            "Prop2B": "2B",
            "Prop2C": "2C",
            "Branch3": [{
                "Prop3A": "3A",
                "Prop3B": "3B",
                "Prop3C": "3C"
            }, {
                "Prop3D": "3D",
                "Prop3E": "3E",
                "Prop3F": "3F"
            }, {
                "Prop3G": "3G",
                "Prop3H": "3H",
                "Prop3I": "3I"
            }]
        },
        "Branch4": [{
            "Prop4A": "4A",
            "Prop4B": "4B",
            "Prop4C": "4C"
        }, {
            "Prop4E": "4E",
            "Prop4F": "4F",
            "Prop4G": "4G"
        }, {
            "Prop4H": "4H",
            "Prop4I": "4I",
            "Prop4I": "4I"
        }]
    }
}

As you can see, the dynamic JSON is composed of hierarchical objects, and these objects are JSON objects, JSON arrays, and JSON properties.

Ultimately, I want to convert this JSON to a List object I can work with in C#. I plan to use that List object to effectively process each JSON branch in document order from the top, down.

Each item in the List collection would be a JObject; each of these objects would have a synthetic "parent" string property that would point back to the branch under which that JObject appears in the original JSON (my examples below explain what I mean by "parent"). [The previous question correctly came up with a solution for this "parent" value, so that's not too relevant to this question... What's new/relevant here is dealing with JArray objects in the JSON...]

The key is that I want each List item object to contain only the string-value properties for the object. For example, Branch1 has string properties Prop1A, 1B, and 1C. Thus, I would want query[0] to contain:

{"Prop1A":"1A","Prop1B":"1B","Prop1C":"1C", Parent:""}

Next, I would want query[2] to contain the string-value properties for Branch2:

{"Prop2A":"2A","Prop2B":"2B","Prop2C":"2C", Parent:"Branch1"}

Next, I would want query[2] to contain the string properties for only Branch3, but because Branch3 is an array of objects, I would want that array to end up together in query[2]:

[
 {"Prop3A": "3A","Prop3B": "3B","Prop3C": "3C"},
 {"Prop3D": "3D","Prop3E": "3E","Prop3F": "3F"},
 {"Prop3G": "3G","Prop3H": "3H","Prop3I": "3I"}
]

Notice that this Branch doesn't yet have a reference to its "Parent"... I'd be happy getting an array in query[2] that looks like the above. (I plan to use dbc's logic to add a "Parent" property to each array element or figure out a way to create a new JObject that contains the array and cites the Parent only once):

[{"Prop3A": "3A","Prop3B": "3B","Prop3C": "3C","Parent":"Branch2"},
 {"Prop3D": "3D","Prop3E": "3E","Prop3F": "3F","Parent":"Branch2"},
 {"Prop3G": "3G","Prop3H": "3H","Prop3I": "3I","Parent":"Branch2"}
]

So, as you can see:

  • I would want any JSON branch that is not an array to be inserted as a new JObject in the query result along with only its string properties and a reference to its parent branch.
  • I would want any JSON branch that is an array to be inserted as a new JObject array in the query result along with only its string properties and a reference to its parent branch.

The trouble I had solving this on my own has to do with figuring out how to create the "if myJsonObject is JArray" condition in Linq and assigning just the string-property properties when the branch is not an array and iterating the array's elements when it is a JArray. I suspect I need to somehow leverage the ? : ternary expression, but I don't exactly know how to do that.

The query from the previous question is here:

var query3 = from o in root.DescendantsAndSelf().OfType<JObject>()      // Find objects
             let l = o.Properties().Where(p => p.Value is JValue)       // Select their primitive properties
             where l.Any()                                              // Skip objects with no properties
             // Add synthetic "Parent" property
             let l2 = l.Concat(new[] { new JProperty("Parent", o.Ancestors().OfType<JProperty>().Skip(1).Select(a => a.Name).FirstOrDefault() ?? "") })
             select new JObject(l2);                                    // And return a JObject.

var list3 = query3.ToList();

That code doesn't handle arrays in the way described above.

Nimantha
  • 6,405
  • 6
  • 28
  • 69
Jazimov
  • 12,626
  • 9
  • 52
  • 59
  • 1
    Your proposed JSON for `query[2]`, simplified to `{ ["Prop3A": "3A"], "Parent": "Branch2" }`, is not valid. From the [standard](http://www.json.org/), a JSON container is either an object - an unordered set of name/value pairs surrounded by braces, or an array - an ordered set of values surrounded by brackets. Your proposed JSON has a value, then a name/value pair, so is neither. Upload to http://jsonlint.com/ and you will see the problem. – dbc Jul 27 '16 at 13:37
  • So sorry--I was tired and completely botched the JSON (I usually use JSLint but didn't in this case...) TY and fixed in question... – Jazimov Jul 27 '16 at 14:56

1 Answers1

0

A suitable and more general answer to this question effectively appears in my related post: Picking Out Simple Properties from Hierarchical JSON

Community
  • 1
  • 1
Jazimov
  • 12,626
  • 9
  • 52
  • 59