Hierarchical json from flat with parent ID
Try something like
var arry = [{ "Id": "1", "Name": "abc", "Parent": "", "attr": "abc" },
{ "Id": "2", "Name": "abc", "Parent": "1", "attr": "abc" },
{ "Id": "3", "Name": "abc", "Parent": "2", "attr": "abc" },
{ "Id": "4", "Name": "abc", "Parent": "2", "attr": "abc" }];
function convert(array){
var map = {};
for(var i = 0; i < array.length; i++){
var obj = array[i];
obj.items= [];
map[obj.Id] = obj;
var parent = obj.Parent || '-';
if(!map[parent]){
map[parent] = {
items: []
};
}
map[parent].items.push(obj);
}
return map['-'].items;
}
var r = convert(arry)
Demo: Fiddle
Result
[{
"Id" : "1",
"Name" : "abc",
"Parent" : "",
"attr" : "abc",
"children" : [{
"Id" : "2",
"Name" : "abc",
"Parent" : "1",
"attr" : "abc",
"children" : [{
"Id" : "3",
"Name" : "abc",
"Parent" : "2",
"attr" : "abc",
"children" : []
}, {
"Id" : "4",
"Name" : "abc",
"Parent" : "2",
"attr" : "abc",
"children" : []
}]
}]
}]
Create Json Hierarchy from from raw data of parent child id
Assuming the data table looks like this:
Map<Integer, Integer> childToParent = new HashMap<>();
childToParent.put(1, 1);
childToParent.put(2, 1);
childToParent.put(3, 1);
childToParent.put(4, 2);
childToParent.put(5, 2);
We can create a parent to children map:
Map<Integer, List<Integer>> parentToChildren = childToParent.entrySet().stream()
.collect(Collectors.groupingBy(Map.Entry::getValue, Collectors.mapping(Map.Entry::getKey, Collectors.toList())));
For simplicity, let's create a Company
class likewise:
@Data
@AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Company {
private final int id;
@JsonProperty(value = "child")
private List<Company> children;
}
Then create Company
objects:
Map<Integer, Company> idToCompany = childToParent.keySet().stream()
.map(integer -> new Company(integer, null))
.collect(Collectors.toMap(Company::getId, company -> company));
And now we can set the children for each parent:
idToCompany.values().forEach(company -> {
List<Integer> childrenIds = parentToChildren.get(company.getId());
if(childrenIds != null){
List<Company> children = childrenIds.stream()
.filter(childId -> childId != company.getId()) // a company can't be a parent of itself
.map(idToCompany::get)
.collect(Collectors.toList());
company.setChildren(children);
}
});
Now we can extract the "head" companies like this:
List<Company> companiesHeads = childToParent.entrySet().stream()
.filter(childIdToParentId -> childIdToParentId.getKey().equals(childIdToParentId.getValue()))
.map(Map.Entry::getKey)
.map(idToCompany::get)
.collect(Collectors.toList());
And print to the screen in JSON format:
ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
System.out.println(mapper.writeValueAsString(companiesHeads));
Output:
[ {
"id" : 1,
"child" : [ {
"id" : 2,
"child" : [ {
"id" : 4
}, {
"id" : 5
} ]
}, {
"id" : 3
} ]
} ]
Hierarchical json to flat with parent ID
You can use recursive function to return one array of objects
var arr =[{"s_gid":0,"title":"scholastic Master List 2016","nodes":[{"Id":"1","templateId":"1","s_gid":"10","m_s_p_id":"1","subject_group_name":"xxxxxxx","parent_id":"1","sname":"","nodes":[{"Id":"2","templateId":"1","s_gid":"100","m_s_p_id":"0","subject_group_name":"abc","parent_id":"10","sname":"","nodes":[{"Id":"3","templateId":"1","s_gid":"1000","m_s_p_id":"0","subject_group_name":"efg","parent_id":"100","sname":""}]}]}]}]
function flatten(data) { var result = []; data.forEach(function(o) { var obj = {} for(var e in o) { (Array.isArray(o[e])) ? result.push(...flatten(o[e])) : obj[e] = o[e]; } result.push(obj) }) return result;}
console.log(flatten(arr))
Convert nested Json to flat Json with parentId to every node
You could take an iterative and recursive approach by using a function which takes an array and a parent id for the actual level.
If a property starts with child
, it calls the function again with the actual _id
and pushes all items to the result set.
function getFlat(array, parentid) { return array.reduce((r, o) => { var temp = {}; r.push(temp); Object.entries(o).forEach(([k, v]) => { if (k.startsWith('child')) { r.push(...getFlat(v, o._id)); } else { temp[k] = v; } }); temp.parentid = parentid; return r; }, []);}
var data = [{ child1: [{ _type: "EntityChild1", name: "Test222", _id: 2 }], child2: [{ _type: "EntityChild2", name: "Test333", _id: 3, child2_child1: [{ _type: "EntityChild2_1", name: "Test444", _id: 6, child2_child1_child1: [{ _type: "EntityChild2_1_1", name: "Test555", _id: 7 }] }] }], _type: "EntityParent", name: "Test000", _id: 1, child3: [{ _type: "EntityChild3", name: "Test111", _id: 4 }], child4: [{ _type: "EntityChild4", name: "Test666", _id: 5 }] }], flat = getFlat(data, -1);
console.log(flat);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Flat JSON unflatten to hierarchy with multiple parents as String
You could use this solution:
var data = [ { "title": "any", "parentids": [] }, { "title": "culture", "parentids": ["any"] }, { "title": "building", "parentids": ["any"] }, { "title": "museum", "parentids": ["culture", "building"] },]
// For each object in data, assign a children property.data.forEach(o => o.children = [])
// For each object in data, assign a key/object pair using the title e.g// { // culture: { "title": "culture", "parentids": ["any"] }} // ... // }const map = data.reduce((a, o) => (a[o.title] = o, a), {})
// For each object in data, and for each parentid in that object,// push this object to the object where the given parentid === IDdata.forEach(o => o.parentids.forEach(id => map[id] && map[id].children.push(o)))
// Filter the data object to only root elements (where there are no parentids)const output = data.filter(e => !e.parentids.length)
console.log(output);
Hierarchical json to flat with parent ID
You can use recursive function to return one array of objects
var arr =[{"s_gid":0,"title":"scholastic Master List 2016","nodes":[{"Id":"1","templateId":"1","s_gid":"10","m_s_p_id":"1","subject_group_name":"xxxxxxx","parent_id":"1","sname":"","nodes":[{"Id":"2","templateId":"1","s_gid":"100","m_s_p_id":"0","subject_group_name":"abc","parent_id":"10","sname":"","nodes":[{"Id":"3","templateId":"1","s_gid":"1000","m_s_p_id":"0","subject_group_name":"efg","parent_id":"100","sname":""}]}]}]}]
function flatten(data) { var result = []; data.forEach(function(o) { var obj = {} for(var e in o) { (Array.isArray(o[e])) ? result.push(...flatten(o[e])) : obj[e] = o[e]; } result.push(obj) }) return result;}
console.log(flatten(arr))
Convert flat data to hierarchical with inner objects javascript
The code below is full source code for your situation. I modified and added a few lines from your source code.
Note that this code assumes that parents are always inserted to this tree before their children do. If this assumption is not always true then your code need to be changed more than this.
let flatData = [
{
"id": 1,
"name": "Sponsor",
"description": null,
"parentId": null
},
{
"id": 2,
"name": "Class",
"description": null,
"parentId": 1
},
{
"id": 3,
"name": "Study",
"description": null,
"parentId": 2
},
{
"id": 4,
"name": "Site",
"description": null,
"parentId": 3
}
];
function convertItem(item) {
let newItem = {};
newItem.data = item;
return newItem;
}
function flatToHierarchy(flat) {
let roots = [];
let all = {};
let ids = [];
flat.forEach(function (item) {
let itemId = item.id;
let convertedItem = convertItem(item);
all[itemId] = convertedItem;
ids.push(itemId);
});
// We use ids array instead of object to maintain its previous order.
for (let i = 0; i < ids.length; i++) {
let id = ids[i];
let convertedItem = all[id];
let parentId = convertedItem.data.parentId;
if (parentId === null) {
delete convertedItem.data.parentId;
delete convertedItem.data.id;
roots.push(convertedItem);
} else if (parentId in all) {
let p = all[parentId];
if (!('Children' in p)) {
p.children = []
}
delete convertedItem.data.parentId;
delete convertedItem.data.id;
p.children.push(convertedItem)
}
};
console.log(roots);
return roots
}
flatToHierarchy(flatData);
We can factor out two deletes before push.
Related Topics
Javascript on Click Event for Multiple Buttons With Same Class
How to Find Previous or Next Element from Array in JavaScript
The Create-React-App Imports Restriction Outside of Src Directory
How to Find Object in a List of Items by Index Using Es6 (Reactjs)
Using Thymeleaf Variable in Onclick Attribute
Select Value of Input Element Inside HTML Table Using Jquery
Image Taken from Camera Not Saved to Gallery
Require(Img Path) Not Working/ Cannot Find Module "." Reactjs
How to Bind on Click Event on Dynamically Created Button in Angular 6
Detect If a Field Is Updated With JavaScript or Jquery
Changing the Browser Zoom Level
How to Prevent Ajax Requests to Follow Redirects Using Jquery
Browserify :- Uncaught Typeerror: Fs.Readfilesync Is Not a Function
Angular 4: How to Read Content of Text File With Httpclient
How to Refresh Form Page After Post Request
Javascript Function Not Defined Error (But It Is Defined)
Localstorage Values Get Reset After Refreshing Page and Inserting New Values