I have this json data which I need to convert into an object. The json has a parent/child relationship instead of actual children object in the parent object.
{
"queryType": "tree",
"queryResultType": "workItemLink",
"workItemRelations": [
{
"rel": null,
"source": null,
"target": {
"id": 1166167,
"url": "https://dev.azure.com/org/_apis/wit/workItems/1166167"
}
},
{
"rel": "System.LinkTypes.Hierarchy-Forward",
"source": {
"id": 1166167,
"url": "https://dev.azure.com/org/_apis/wit/workItems/1166167"
},
"target": {
"id": 1167481,
"url": "https://dev.azure.com/org/_apis/wit/workItems/1167481"
}
},
{
"rel": "System.LinkTypes.Hierarchy-Forward",
"source": {
"id": 1167481,
"url": "https://dev.azure.com/org/_apis/wit/workItems/1167481"
},
"target": {
"id": 1234896,
"url": "https://dev.azure.com/org/_apis/wit/workItems/1234896"
}
}
]
}
What I've done so far. Please note that the code below is not the actual code but are snippets I took from the actual code for simplicity.
import axios from 'axios';
interface Item {
id: number;
children: Item[];
}
interface WiqlResponse {
queryType: string;
queryResultType: string;
asOf: string;
workItemRelations: Array<{
rel: string;
source: { id: number; url: string } | null;
target: { id: number; url: string };
}>
}
export async function getWiql(wiql: string): Promise<WiqlResponse> {
const response = await axios.get<WiqlResponse>(`/org/_apis/wit/wiql/${wiql}?api-version=7.1`);
return response.data;
}
export async function main() {
getWiql('123123213').then(wiqlResponse => {
// Get all parent work items
for (const pRel of wiqlResponse.workItemRelations.filter(r => r.rel == null)) {
let childs: Item[] = [];
// Get all children of this parent
for (const cRel of wiqlResponse.workItemRelations.filter(r => r.source?.id == pRel.target.id)) {
let child: Item = {
id: cRel.target.id,
children: []
};
childs.push(child);
}
let parent: Item = {
id: pRel.target.id,
children: childs
};
}
});
}
The code above will work up to level 2 only but if you look closely at the json data, it has 3 level and could be more depending on the data from the source.
How can I recursively check if there are still child items?
EDIT: Here's a sample code that can be run without axios.
interface Item {
id: number;
children: Item[];
}
interface WiqlResponse {
workItemRelations: Array<{
rel: string | null;
source: { id: number; url: string } | null;
target: { id: number; url: string };
}>
}
const wiqlResponse: WiqlResponse = {
"workItemRelations": [
{
"rel": null,
"source": null,
"target": {
"id": 1166167,
"url": "https://dev.azure.com/org/_apis/wit/workItems/1166167"
}
},
{
"rel": "System.LinkTypes.Hierarchy-Forward",
"source": {
"id": 1166167,
"url": "https://dev.azure.com/org/_apis/wit/workItems/1166167"
},
"target": {
"id": 1167481,
"url": "https://dev.azure.com/org/_apis/wit/workItems/1167481"
}
},
{
"rel": "System.LinkTypes.Hierarchy-Forward",
"source": {
"id": 1167481,
"url": "https://dev.azure.com/org/_apis/wit/workItems/1167481"
},
"target": {
"id": 1234896,
"url": "https://dev.azure.com/org/_apis/wit/workItems/1234896"
}
}
]
};
export async function main() {
console.log('wiqlResponse: ', wiqlResponse);
let items: Item[] = [];
// Get all parent work items
for (const pRel of wiqlResponse.workItemRelations.filter(r => r.rel == null)) {
let childs: Item[] = [];
// Get all children of this parent
for (const cRel of wiqlResponse.workItemRelations.filter(r => r.source?.id == pRel.target.id)) {
let child: Item = {
id: cRel.target.id,
children: []
};
childs.push(child);
}
let parent: Item = {
id: pRel.target.id,
children: childs
};
items.push(parent);
}
console.log('items:', JSON.stringify(items));
}
main();
EDIT: Apologies for not explaining the relationship of the json data.
The json provides a relationship between source and target. The target is a top most parent if it doesn't have a source. If the relationship has both source and target, the target is the child of the source.
EDIT: Adding the expected result for clarity. Again my apologies for not being concise the first time.
The expected result should be:
[
{
"id": 1166167,
"children": [
{
"id": 1167481,
"children": [
{
"id": 1234896,
"children": []
}
]
}
]
}
]