I have an umbraco website with the following content structure:
(the text in brackets is the nodeTypeAlias)
[root]
- [child]
| - [module]
| | - [submodule]
| | - [submodule]
- [child]
| - [module]
| - [module]
| | - [submodule]
I am trying to export the above structure (together with the node's properties) into the following json file:
{
"root": {
"child": [
{
"id": "1",
"name": "Child 1",
"module": [
{
"id": "2",
"name": "Module 1",
"submodule": [
{
"id": "3",
"name": "Sub module 1"
},
{
"id": "4",
"name": "Sub module 3"
}
]
}
]
},
{
"id": "5",
"name": "Child 5",
"module": [
{
"id": "8",
"name": "Module 8"
},
{
"id": "6",
"name": "Module 6",
"submodule": [
{
"id": "7",
"name": "Sub module 7"
},
{
"id": "9",
"name": "Sub module 9"
}
]
}
]
}
]
}
}
So far I've wrote down the following code in Linqpad but the result is not the one that I was looking for.
List<Node> brands = new List<Node>()
{
new Node
{
id = 1,
name = "Brand 1",
type = "brand",
children = new List<Node>
{
new Node
{
id = 2,
name = "Shelf 1",
type = "shelf",
children = new List<Node>
{
new Node
{
id = 1,
name = "Bookcase 1",
type = "bookcase"
},
new Node
{
id = 2,
name = "Bookcase 2",
type = "bookcase"
},
new Node
{
id = 3,
name = "Bookcase 3",
type = "bookcase"
}
}
},
new Node
{
id = 3,
name = "Shelf 2",
type = "shelf",
children = new List<Node>
{
new Node
{
id=1,
type= "module",
name = "Module 1"
},
new Node
{
id=2,
type= "pdf",
name = "PDF 1"
},
new Node
{
id=3,
type= "link",
name = "Link 1"
},
new Node
{
id=4,
type= "link",
name = "Link 2"
},
}
}
}
},
new Node
{
id = 2,
name = "Brand 2",
type = "brand",
children = new List<Node>
{
new Node
{
id = 2,
name = "Shelf 1",
type = "shelf",
},
new Node
{
id = 3,
name = "Shelf 2",
type = "shelf",
}
}
}
};
Result container = new Result();
Action<List<Node>, Result> add = null;
add = (nodes, coll) =>
{
List<Result> list = null;
if(nodes != null && nodes.Count > 0)
{
nodes.Dump("nodes");
foreach(var node in nodes)
{
string key = node.type;
list = null;
if(coll.Children.ContainsKey(key))
{
list = coll.Children[key];
}
else
{
list = new List<Result>();
}
Result r = new Result();
r.Name = node.name;
add(node.children, r);
list.Add(r);
coll.Children[key] = list;
coll.Dump("coll");
}
}
};
add(brands, container);
container.Dump();
var serializer = new JavaScriptSerializer();
serializer.Serialize(container).Dump();
}
public class Result
{
public Result()
{
this.Children = new Dictionary<string, List<Result>>();
this.Properties = new Dictionary<string, string>();
}
public string Name {get;set;}
public Dictionary<string, string> Properties {get;set;}
public Dictionary<string, List<Result>> Children {get;set;}
}
public class Node
{
public string name{get;set;}
public string type {get;set;}
public int id {get;set;}
public List<Node> children{get;set;}
result:
{
"Name": null,
"Properties": {},
"Children": {
"brand": [
{
"Name": "Brand 1",
"Properties": {},
"Children": {
"shelf": [
{
"Name": "Shelf 1",
"Properties": {},
"Children": {
"bookcase": [
{
"Name": "Bookcase 1",
"Properties": {},
"Children": {}
},
{
"Name": "Bookcase 2",
"Properties": {},
"Children": {}
},
{
"Name": "Bookcase 3",
"Properties": {},
"Children": {}
}
]
}
},
{
"Name": "Shelf 2",
"Properties": {},
"Children": {
"module": [
{
"Name": "Module 1",
"Properties": {},
"Children": {}
}
],
"pdf": [
{
"Name": "PDF 1",
"Properties": {},
"Children": {}
}
],
"link": [
{
"Name": "Link 1",
"Properties": {},
"Children": {}
},
{
"Name": "Link 2",
"Properties": {},
"Children": {}
}
]
}
}
]
}
},
{
"Name": "Brand 2",
"Properties": {},
"Children": {
"shelf": [
{
"Name": "Shelf 1",
"Properties": {},
"Children": {}
},
{
"Name": "Shelf 2",
"Properties": {},
"Children": {}
}
]
}
}
]
}
}
Any idea?
Thanks.
This is very much the way that you would go about generating XML, but JSON is a little different. If you have updated your Umbraco to one of the later editions, then you use Razor to render JSON in this sort of way:
#{
var builder = new System.Text.StringBuilder();
foreach (var car in cars)
{
builder.Append("{");
builder.Append(Json.Encode("reg") + ":" + Json.Encode(car.Registration) + ",");
builder.Append(Json.Encode("model") + ":" + car.Model);
// INSERT OTHER VALUES HERE
builder.Append("}");
if (car.Registration != cars.Last().Registration)
{
builder.Append(",");
}
count++;
}
}
#Html.Raw(builder.ToString())
Another more interesting way is JSON.NET - a good option if you are using custom objects in your application. You populate your objects, and then pass them through JSON.NET. See here for more details.
Product product = new Product();
product.Name = "Apple";
product.Expiry = new DateTime(2008, 12, 28);
product.Price = 3.99M;
product.Sizes = new string[] { "Small", "Medium", "Large" };
string json = JsonConvert.SerializeObject(product);
//{
// "Name": "Apple",
// "Expiry": "2008-12-28T00:00:00",
// "Price": 3.99,
// "Sizes": [
// "Small",
// "Medium",
// "Large"
// ]
//}
Product deserializedProduct = JsonConvert.DeserializeObject(json);
The beauty of this library is that you can also create strings and convert them to JSON. The only caveat is that you have to watch your JavaScript when trying to read the JSON. Things like single (') and double (") quotes can break your code.
string json = #"{
""Name"": ""Apple"",
""Expiry"": "2008-12-28T00:00:00",
""Price"": 3.99,
""Sizes"": [
""Small"",
""Medium"",
""Large""
]
}";
JObject o = JObject.Parse(json);
string name = (string)o["Name"];
// Apple
JArray sizes = (JArray)o["Sizes"];
string smallest = (string)sizes[0];
// Small
Your code could work if you used the System.Xml namespace (XmlDocument, XmlAttributes, XmlNode). It is unclear as to which Node object you are using but I will assume it is Umbraco's Node (I would work with a new DynamicNode() instead btw) and in which case you cannot just create them like that with populated properties. You have to create one in the Umbraco database before reading its values.
Hopefully this should give you something to go on with. Happy coding.
Related
I have an array like this coming from API response and I want to filter by nested property products to returns product with only id 11
"assets": [
{
"name": "abc",
"products": [
{
"id": "11",
"status": true
},
{
"id": "14",
"status": null
}
]
},
{
"name": "xyz",
"products": [
{
"id": "11",
"status": true
},
{
"id": "28",
"status": null
}
]
},
{
"name": "123",
"products": [
{
"id": "48",
"status": null
}
]
},
{
"name": "456",
"products": [
{
"id": "11",
"status": true
}
]
}
]
the resulting output should look like this,
"assets": [
{
"name": "abc",
"products": [
{
"id": "11",
"status": true
}
]
},
{
"name": "xyz",
"products": [
{
"id": "11",
"status": true
}
]
},
{
"name": "123",
"products": []
},
{
"name": "456",
"products": [
{
"id": "11",
"status": true
}
]
}
]
I'm trying to return filter output with the C# LINQ method. but, getting an error when filtering a nested array with the following method
"Cannot convert lambda expression to intended delegate type because some of the return types in the block are not implicitly convertible to the delegate return type"
assets.Select(asset => asset.products.Where(product => product.id == "11")).ToArray();
You can just remove all items from every products array, whose id doesn't equal 11. Parse JSON to JObject, iterate over assets array, find products with id different from 11 and remove them form original array
var json = JObject.Parse(jsonString);
foreach (var asset in json["assets"])
{
var productsArray = asset["products"] as JArray;
if (productsArray == null)
continue;
var productsToRemove = productsArray
.Where(o => o?["id"]?.Value<int>() != 11)
.ToList();
foreach (var product in productsToRemove)
productsArray.Remove(product);
}
Console.WriteLine(json);
Instead of Select and Applying a, Where try to remove the Products that you do not want.
Following is a sample code.
class Program
{
static void Main(string[] args)
{
var json = #"
{
'assets': [
{
'name': 'abc',
'products': [
{
'id': '11',
'status': true
},
{
'id': '14',
'status': null
}
]
},
{
'name': 'xyz',
'products': [
{
'id': '11',
'status': true
},
{
'id': '28',
'status': null
}
]
},
{
'name': '123',
'products': [
{
'id': '48',
'status': null
}
]
},
{
'name': '456',
'products': [
{
'id': '11',
'status': true
}
]
}
]}";
var root = JsonConvert.DeserializeObject<Root>(json);
var assets = root.Assets;
assets.ForEach(a =>
{
a.Products.RemoveAll(p => p.Id != 11);
});
}
}
public partial class Root
{
[JsonProperty("assets")]
public List<Asset> Assets { get; set; }
}
public partial class Asset
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("products")]
public List<Product> Products { get; set; }
}
public partial class Product
{
[JsonProperty("id")]
public long Id { get; set; }
[JsonProperty("status")]
public bool? Status { get; set; }
}
To filter the list, you will need to create a new list with products whose ID == YourId. Following linq query does the necessary steps to create the list you want.
Filter out any assets that dont have any product with ID == 11. This is necessary to skip nulls in the new list that will be generated (Where statement)
Create a collection / list of new assets that only have the products whose ID == 11 (Select statement)
var list = assets.Where(x => x.Products.Where(y => y.Id.Equals("11")).Count() > 0)
.Select(asset => {
return new Asset() {
Name = asset.Name,
Products = asset.Products.Where(x => x.Id == "11").ToList()
};
}).ToList();
// Create the RootObject that holds a list of all the arrays if you want.
Rootobject newAssetCollection = new Rootobject() { Assets = list };
Below is the Json that was printed
Console.WriteLine(JsonConvert.SerializeObject(newAssetCollection, Formatting.Indented));
{
"assets": [
{
"name": "abc",
"products": [
{
"id": "11",
"status": true
}
]
},
{
"name": "xyz",
"products": [
{
"id": "11",
"status": true
}
]
},
{
"name": "456",
"products": [
{
"id": "11",
"status": true
}
]
}
]
}
I'm wondering if someone can elucidate a method to sort a list of objects based on a child object's attribute.
I'm working with the following model:
public class Content
{
public string Id { get; set; }
public List<ContentAttribute> Attributes { get; set; }
}
public class ContentAttribute
{
public string Value { get; set; }
public string Id { get; set; }
public string Name { get; set; }
}
Some sample data:
[
{
"Id": "123",
"Attributes": [
{
"Value": "abc",
"Id": "1a",
"Name": "name1"
},
{
"Value": "ghi",
"Id": "2b",
"Name": "name2"
}
]
},
{
"Id": "456",
"Attributes": [
{
"Value": "abc",
"Id": "1a",
"Name": "name2"
},
{
"Value": "def",
"Id": "2b",
"Name": "name3"
}
]
},
{
"Id": "789",
"Attributes": [
{
"Value": "abc",
"Id": "1a",
"Name": "name1"
},
{
"Value": "def",
"Id": "2b",
"Name": "name2"
}
]
}
]
How can I sort the Content objects by the Value of a specific attribute Name? For example, I would like to sort the above data by the Value of 'name2',
meaning the result would be
[
{"Id" : "456"},
{"Id" : "789"},
{"Id" : "123"}
]
Any help is greatly appreciated. (Using c#).
If Attributes always has an element with name name2 and you want an exception if it doesn't then:
var sorted = contents.OrderBy(c => c.Attributes.First(a => a.Name == "name2").Value).ToList();
Or if name2 could be missing and it's not deal breaker then use FirstOrDefault
var sorted = contents.OrderBy(c => c.Attributes.FirstOrDefault(a => a.Name == "name2")?.Value).ToList();
Hi I would like to use the json collection from the code below in an angular repeater.
I need to give the collection a name but i dont know how
this is the code to generate the JSON
public JsonResult GetProducts()
{
var result = db.Products.ToList();
var list = JsonConvert.SerializeObject(result, Formatting.None, new JsonSerializerSettings(){ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore});
return Json(list,JsonRequestBehavior.AllowGet);
}
and this is the result
[{
"Category": {
"ID": 4,
"Name": "TEST"
},
"OrderDetails": [],
"ID": 10006,
"Description": "TEST",
"Name": "TEST",
"Price": 3.20,
"PictureUrl":"",
"CategoryId": 4,
"AddedToShop": "2016-12-11T14:52:57.677"
},
{
"Category": {
"ID": 4,
"Name": "TEST"
},
"OrderDetails": [],
"ID": 20005,
"Description": "TEST2",
"Name": "TEST2",
"Price": 3.20,
"PictureUrl":"",
"CategoryId": 4,
"AddedToShop": "2016-12-12T12:02:10.593"
}]
and I would like it to be like the code below so I can use the products tag to iterate .
{
"products": [{
"Category": {
"ID": 4,
"Name": "TEST"
},
"OrderDetails": [],
"ID": 10006,
"Description": "TEST",
"Name": "TEST",
"Price": 3.20,
"PictureUrl":"",
"CategoryId": 4,
"AddedToShop": "2016-12-11T14:52:57.677"
},
{
"Category": {
"ID": 4,
"Name": "TEST"
},
"OrderDetails": [],
"ID": 20005,
"Description": "TEST2",
"Name": "TEST2",
"Price": 3.20,
"PictureUrl":"",
"CategoryId": 4,
"AddedToShop": "2016-12-12T12:02:10.593"
}]}
If you are using WebAPI controllers you don't need to send JsonResult, all you need to do is create a class and send it back to client:
public class MyClass
{
public List<Product> Products { get; set; }
}
And in your controller:
public MyClass Get() {
return new MyClass {
Products = db.Products.ToList()
};
}
OR:
Simply create your object and then pass it in the serializer:
JsonConvert.SerializeObject( { "products": result }, Formatting.None, new JsonSerializerSettings(){ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore})
You can use
var list = JsonConvert.SerializeObject(new { products = result }, Formatting.None, new JsonSerializerSettings() { ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore });
One solution for your problem is, define a seperate class and define a property for that class as either a collection or list of the type "db.Products"(Use the appropriate class name for this object as you have in your code) and when you serialize that object you will get it as you have asked for
class ProductList
{
public Collection<YourType> Products{get; set;}
}
OR
class ProductList
{
public List<YourType> Products{get; set;}
}
I have this json:
{
"treeview":[
{
"text":"blah",
"nodes":[
]
},
{
"text":"blah",
"nodes":[
]
},
{
"text":"blah",
"nodes":[
{
"text":"blah",
"nodes":[
{
"text":"foo",
"nodes":[
// I need to put data in here !!!
]
}
]
}
]
},
{
"text":"blah",
"nodes":[
]
},
{
"text":"foo",
"nodes":[
// Not here !
]
}
]
}
I need to put value on "nodes" element where i'm on level 2 and the "text" equals "foo".
Here's what I've tried so far:
var json = myJson;
// First approach
var selector = (JArray)json.SelectTokens($"$..treeview[?(#.text == 'foo')]");
// Second approach
var selector2 = (JArray)json.SelectToken($"$.treeview[?(#...text == 'foo')]");
selector.Add(new JObject(new JProperty("text", "myValue"));
I don't understand how the "dot" in the query works... I just know that when you type 2 "dot" it browse the entire JSON... Is there a way to query a particular indent level only ?
I figured it out, yes we can specify a level indentation when we want to query a json in text plain, here's how:
var json = myJson;
var selector = (JArray)json.SelectTokens($"$.treeview[*].nodes[*].nodes[(#.text =='foo')].nodes");
selector.Add(new JObject(new JProperty("text", "myValue")));
You can test it here: http://jsonpath.com/
copy past my json sample in the json section and add this in the jsonPath: $.treeview[*].nodes[*].nodes[*].text
That's how you can get the 'foo' value in the desired "level of identation" without specified any index in the arrays, just use this '*' instead of an int
You need to specify the correct path to the "nodes" array. Try this:
JObject json = JObject.Parse("{\"treeview\":[{\"text\":\"blah\",\"nodes\":[]},{\"text\":\"blah\",\"nodes\":[]},{\"text\":\"blah\",\"nodes\":[{\"text\":\"blah\",\"nodes\":[{\"text\":\"foo\",\"nodes\":[]}]}]},{\"text\":\"blah\",\"nodes\":[]},{\"text\":\"foo\",\"nodes\":[]}]}");
JArray array = (JArray)json.SelectToken("treeview[2].nodes[0].nodes[0].nodes");
array.Add(new JObject(new JProperty("text", "myValue")));
It is much easier to work with objects than just plain json text...
using Newtonsoft.Json package...
class Program
{
static void Main(string[] args)
{
var jsonstring = "{\"text\":\"blah\",\"nodes\":[{\"text\":\"foo\", \"nodes\": []}, {\"text\":\"bar\", \"nodes\": []}, {\"text\":\"foo\", \"nodes\": []}]}";
//This is the root node
var firstLevelNodes = JsonConvert.DeserializeObject<Node>(jsonstring);
//All the nodes in the root nodes node collection
var secondLevelNodes = firstLevelNodes.nodes;
//All of the nodes in the collections of the second level nodes
var thirdLevelNodes = secondLevelNodes.SelectMany(sln => sln.nodes);
Console.WriteLine("First Level Nodes: \n" + JsonConvert.SerializeObject(firstLevelNodes).PrettyPrint());
Console.WriteLine();
Console.WriteLine("Second Level Nodes: \n" + JsonConvert.SerializeObject(secondLevelNodes).PrettyPrint());
Console.WriteLine();
Console.WriteLine("Third Level Nodes: \n" + JsonConvert.SerializeObject(thirdLevelNodes).PrettyPrint());
secondLevelNodes.First().nodes = new List<Node> { new Node { text = "new node" , nodes = new List<Node>() } };
Console.WriteLine();
Console.WriteLine("Third Level Nodes (with new node): \n" + JsonConvert.SerializeObject(thirdLevelNodes).PrettyPrint());
Console.ReadLine();
}
}
public static class JSONExtensions
{
public static string PrettyPrint(this string json)
{
dynamic parsedJson = JsonConvert.DeserializeObject(json);
return JsonConvert.SerializeObject(parsedJson, Formatting.Indented);
}
}
[Serializable]
public class Node
{
public string text { get; set; }
public IEnumerable<Node> nodes { get; set; }
}
OUTPUT:
First Level Nodes:
{
"text": "blah",
"nodes": [
{
"text": "foo",
"nodes": []
},
{
"text": "bar",
"nodes": []
},
{
"text": "foo",
"nodes": []
}
]
}
Second Level Nodes:
[
{
"text": "foo",
"nodes": []
},
{
"text": "bar",
"nodes": []
},
{
"text": "foo",
"nodes": []
}
]
Third Level Nodes:
[]
Third Level Nodes (with new node):
[
{
"text": "new node",
"nodes": []
}
]
EDIT:
So if you only wanted the second level nodes that had the text foo just use..
var secondLevelFooNodes = secondLevelNodes.Where(sln=>sln.text == "foo");
//then use these nodes
EDIT2:
Using the your actual JSON object requires a TreeView Class as well...
class Program
{
static void Main(string[] args)
{
var jsonstring = "{\"treeview\":[{\"text\":\"blah\",\"nodes\":[]},{\"text\":\"blah\",\"nodes\":[]},{\"text\":\"blah\",\"nodes\":[{\"text\":\"blah\",\"nodes\":[{\"text\":\"foo\",\"nodes\":[]}]}]},{\"text\":\"blah\",\"nodes\":[]},{\"text\":\"foo\",\"nodes\":[]}]}";
//This is the root node
var treeView = JsonConvert.DeserializeObject<TreeView>(jsonstring);
//All the nodes in the root nodes node collection
var firstLevelNodes = treeView.treeview;
//All of the nodes in the collections of the first level nodes
var secondLevelNodes = firstLevelNodes.SelectMany(fln => fln.nodes);
//All of the nodes in the collections of the second level nodes
var thirdLevelNodes = secondLevelNodes.SelectMany(sln => sln.nodes);
Console.WriteLine("The TreeView: \n" + JsonConvert.SerializeObject(treeView, Formatting.Indented));
thirdLevelNodes.First(sln => sln.text == "foo").nodes = new List<Node> { new Node { text = "new node", nodes = new List<Node>() } };
Console.WriteLine();
Console.WriteLine("The TreeView (with new node): \n" + JsonConvert.SerializeObject(treeView, Formatting.Indented));
Console.ReadLine();
}
}
[Serializable]
public class Node
{
public string text { get; set; }
public IEnumerable<Node> nodes { get; set; }
}
[Serializable]
public class TreeView
{
public IEnumerable<Node> treeview { get; set; }
}
OUTPUT:
The TreeView:
{
"treeview": [
{
"text": "blah",
"nodes": []
},
{
"text": "blah",
"nodes": []
},
{
"text": "blah",
"nodes": [
{
"text": "blah",
"nodes": [
{
"text": "foo",
"nodes": []
}
]
}
]
},
{
"text": "blah",
"nodes": []
},
{
"text": "foo",
"nodes": []
}
]
}
The TreeView (with new node):
{
"treeview": [
{
"text": "blah",
"nodes": []
},
{
"text": "blah",
"nodes": []
},
{
"text": "blah",
"nodes": [
{
"text": "blah",
"nodes": [
{
"text": "foo",
"nodes": [
{
"text": "new node",
"nodes": []
}
]
}
]
}
]
},
{
"text": "blah",
"nodes": []
},
{
"text": "foo",
"nodes": []
}
]
}
C# | .NET 4.5 | Entity Framework 5
I have data coming back from a SQL Query in the form of ID,ParentID,Name. I'd like to take that data and parse it into a Hierarchical JSON string. So far it seems to be much more of a daunting task than it should be. Since I'm using Entity the data comes back nicely to me as an IEnumerable. Now I believe I just need some form of recursion, but I'm not quite sure where to start. Any help is appreciated.
Data Returns as
id parentId name
1 1 TopLoc
2 1 Loc1
3 1 Loc2
4 2 Loc1A
Code is
public static string GetJsonLocationHierarchy(long locationID)
{
using (EntitiesSettings context = new EntitiesSettings())
{
// IEnumerable of ID,ParentID,Name
context.GetLocationHierarchy(locationID);
}
}
The end result I'd hope would be something like this:
{
"id": "1",
"parentId": "1",
"name": "TopLoc",
"children": [
{
"id": "2",
"parentId": "1",
"name": "Loc1",
"children": [
{
"id": "4",
"parentId": "2",
"name": "Loc1A",
"children": [
{}
]
}
]
},
{
"id": "3",
"parentId": "1",
"name": "Loc2",
"children": [
{}
]
}
]
}
One way to turn a flat table into a hierarchy is to put all your nodes into a dictionary. Then iterate over the dictionary, and for each node, look up its parent and add it to the parent's children. From there, you just need to find the root and serialize it.
Here is an example program to demonstrate the approach:
class Program
{
static void Main(string[] args)
{
IEnumerable<Location> locations = new List<Location>
{
new Location { Id = 1, ParentId = 1, Name = "TopLoc" },
new Location { Id = 2, ParentId = 1, Name = "Loc1" },
new Location { Id = 3, ParentId = 1, Name = "Loc2" },
new Location { Id = 4, ParentId = 2, Name = "Loc1A" },
};
Dictionary<int, Location> dict = locations.ToDictionary(loc => loc.Id);
foreach (Location loc in dict.Values)
{
if (loc.ParentId != loc.Id)
{
Location parent = dict[loc.ParentId];
parent.Children.Add(loc);
}
}
Location root = dict.Values.First(loc => loc.ParentId == loc.Id);
JsonSerializerSettings settings = new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
Formatting = Formatting.Indented
};
string json = JsonConvert.SerializeObject(root, settings);
Console.WriteLine(json);
}
}
class Location
{
public Location()
{
Children = new List<Location>();
}
public int Id { get; set; }
public int ParentId { get; set; }
public string Name { get; set; }
public List<Location> Children { get; set; }
}
Here is the output:
{
"id": 1,
"parentId": 1,
"name": "TopLoc",
"children": [
{
"id": 2,
"parentId": 1,
"name": "Loc1",
"children": [
{
"id": 4,
"parentId": 2,
"name": "Loc1A",
"children": []
}
]
},
{
"id": 3,
"parentId": 1,
"name": "Loc2",
"children": []
}
]
}