I am struggling to build the JSON hierarchy structure from the raw response JSON which I am getting from other API.
I want to generate a hierarchy structure from raw JSON Response on the basis of parent KPI and child KPI names relationship, which I am pulling from database for this example I have added the relationship table list below. I have Added a sample POC code in update, please check at the end.
Relationship list:
// Sample relationship data
var relationships = new List<Relationship>
{
new Relationship { KpiGroupName = "Operations & Asset Performance", ParentKpiName = "EquipAvailability", ChildKpiName = "total_downtime_hours", ParentKpiDisplayName = "Availability", ChildKpiDisplayName = "Total Downtime" },
new Relationship { KpiGroupName = "Operations & Asset Performance", ParentKpiName = "total_downtime_hours", ChildKpiName = "scheduled_downtime_hours", ParentKpiDisplayName = "Total Downtime", ChildKpiDisplayName = "Scheduled Downtime" },
new Relationship { KpiGroupName = "Operations & Asset Performance", ParentKpiName = "total_downtime_hours", ChildKpiName = "unscheduled_downtime_hours", ParentKpiDisplayName = "Total Downtime", ChildKpiDisplayName = "Unscheduled Downtime" },
new Relationship { KpiGroupName = "Operations & Asset Performance", ParentKpiName = "ops_availability", ChildKpiName = "mttr", ParentKpiDisplayName = "Operational Availability", ChildKpiDisplayName = "MTTR" },
new Relationship { KpiGroupName = "Operations & Asset Performance", ParentKpiName = "ops_availability", ChildKpiName = "mtbf", ParentKpiDisplayName = "Operational Availability", ChildKpiDisplayName = "MTFB" },
new Relationship { KpiGroupName = "Operations & Asset Performance", ParentKpiName = "ops_availability", ChildKpiName = "mtbm", ParentKpiDisplayName = "Operational Availability", ChildKpiDisplayName = "MTFB" },
new Relationship { KpiGroupName = "Operations & Asset Performance", ParentKpiName = "ops_availability", ChildKpiName = "Operational_Running_Hours", ParentKpiDisplayName = "Operational Availability", ChildKpiDisplayName = "Operational Running Hours" },
new Relationship { KpiGroupName = "Operations & Asset Performance", ParentKpiName = "mttr", ChildKpiName = "total_downtime_hours_wts", ParentKpiDisplayName = "MTTR", ChildKpiDisplayName = "Total Downtime Hours of BD,NT" },
new Relationship { KpiGroupName = "Operations & Asset Performance", ParentKpiName = "mttr", ChildKpiName = "unscheduled_downtime_hours_bd_in_ops", ParentKpiDisplayName = "MTTR", ChildKpiDisplayName = "Total Downtime Hours of BD in Ops" },
new Relationship { KpiGroupName = "Operations & Asset Performance", ParentKpiName = "mtbf", ChildKpiName = "number_of_breakdowns", ParentKpiDisplayName = "MTFB", ChildKpiDisplayName = "Number Of Breakdowns" },
new Relationship { KpiGroupName = "Operations & Asset Performance", ParentKpiName = "mtbm", ChildKpiName = "Number of Maintainance Actions", ParentKpiDisplayName = "MTFB", ChildKpiDisplayName = "Number of Maintainance Actions" },
new Relationship { KpiGroupName = "Operations & Asset Performance", ParentKpiName = "Operational_Running_Hours", ChildKpiName = "Utilization", ParentKpiDisplayName = "Operational Running Hours", ChildKpiDisplayName = "Utilization" },
new Relationship { KpiGroupName = "Operations & Asset Performance", ParentKpiName = "Operational_Running_Hours", ChildKpiName = "Total Moves", ParentKpiDisplayName = "Operational Running Hours", ChildKpiDisplayName = "Total Moves" },
new Relationship { KpiGroupName = "Operations & Asset Performance", ParentKpiName = "Operational_Running_Hours", ChildKpiName = "Idle Hours", ParentKpiDisplayName = "Operational Running Hours", ChildKpiDisplayName = "Idle Hours" },
new Relationship { KpiGroupName = "Operations & Asset Performance", ParentKpiName = "Operational_Running_Hours", ChildKpiName = "Equipment Efficiency", ParentKpiDisplayName = "Operational Running Hours", ChildKpiDisplayName = "Equipment Efficiency" }
};
Expected JSON:
[
{
"dimensions": {
"vw_asset_mgmt.month_code": "202503",
"vw_asset_mgmt.terminal_code": "T001"
},
"hierarchy": {
"group_name": "Operations & Asset Performance",
"EquipAvailability": {
"display_name": "Availability",
"value": 98.5,
"sub_levels": {
"total_downtime_hours": {
"display_name": "Total Downtime",
"value": 120.5,
"sub_levels": {
"scheduled_downtime_hours": {
"display_name": "Scheduled Downtime",
"value": 50.0
},
"unscheduled_downtime_hours": {
"display_name": "Unscheduled Downtime",
"value": 70.5
}
}
}
}
},
"ops_availability": {
"display_name": "Operations Availability",
"value": 95.0,
"sub_levels": {
"mttr": {
"display_name": "MTTR",
"value": 1.5,
"sub_levels": {
"total_downtime_hours_wts": {
"display_name": "Total Downtime Hours of BD,NT",
"value": 110.0
}
}
},
"mtbf": {
"display_name": "MTBF",
"value": 500.0
"sub_levels": {
"number_of_breakdowns": {
"display_name": "Number Of Breakdowns",
"value": 5
}
}
},
"Operational_Running_Hours": {
"display_name": "Operational Running Hours",
"value": 4000.0
}
}
}
}
},
{
"dimensions": {
"vw_asset_mgmt.month_code": "202502",
"vw_asset_mgmt.terminal_code": "T002"
},
"hierarchy": {
"group_name": "Operations & Asset Performance",
"EquipAvailability": {
"display_name": "Availability",
"value": 97.0,
"sub_levels": {
"total_downtime_hours": {
"display_name": "Total Downtime",
"value": 140.0,
"sub_levels": {
"scheduled_downtime_hours": {
"display_name": "Scheduled Downtime",
"value": 55.0
},
"unscheduled_downtime_hours": {
"display_name": "Unscheduled Downtime",
"value": 85.0
}
}
}
}
},
"ops_availability": {
"display_name": "Operations Availability",
"value": 94.5,
"sub_levels": {
"mttr": {
"display_name": "MTTR",
"value": 1.8,
"sub_levels": {
"total_downtime_hours_wts": {
"display_name": "Total Downtime Hours of BD,NT",
"value": 130.0
}
}
},
"mtbf": {
"display_name": "MTBF",
"value": 480.0,
"sub_levels": {
"number_of_breakdowns": {
"display_name": "Number Of Breakdowns",
"value": 6
}
}
},
"Operational_Running_Hours": {
"display_name": "Number Of Breakdowns"
"value": 3900.0
}
}
}
}
}
]
And I have below raw JSON from other API response:
[
{
"kpIs": [
{
"kpiName": "vw_asset_mgmt.EquipAvailability",
"kpiValue": "100"
},
{
"kpiName": "vw_asset_mgmt.total_downtime_hours",
"kpiValue": "980"
},
{
"kpiName": "vw_asset_mgmt.scheduled_downtime_hours",
"kpiValue": "450"
},
{
"kpiName": "vw_asset_mgmt.unscheduled_downtime_hours",
"kpiValue": "90"
},
{
"kpiName": "vw_asset_mgmt.ops_availability",
"kpiValue": "96"
},
{
"kpiName": "vw_asset_mgmt.mttr",
"kpiValue": "980"
},
{
"kpiName": "vw_asset_mgmt.total_downtime_hours_wts",
"kpiValue": "40"
},
{
"kpiName": "vw_asset_mgmt.unscheduled_downtime_hours_bd_in_ops",
"kpiValue": "320"
},
{
"kpiName": "vw_asset_mgmt.mtbf",
"kpiValue": "87"
},
{
"kpiName": "vw_asset_mgmt.number_of_breakdowns",
"kpiValue": "100"
},
{
"kpiName": "vw_asset_mgmt.Operational_Running_Hours",
"kpiValue": "98"
}
],
"dimensions": [
{
"dimensionName": "vw_asset_mgmt.month_code",
"dimensionValue": "202502"
},
{
"dimensionName": "vw_asset_mgmt.terminal_code",
"dimensionValue": "PEC2"
}
]
},
{
"kpIs": [
{
"kpiName": "vw_asset_mgmt.EquipAvailability",
"kpiValue": "100"
},
{
"kpiName": "vw_asset_mgmt.total_downtime_hours",
"kpiValue": "98"
},
{
"kpiName": "vw_asset_mgmt.scheduled_downtime_hours",
"kpiValue": "877"
},
{
"kpiName": "vw_asset_mgmt.unscheduled_downtime_hours",
"kpiValue": "656"
},
{
"kpiName": "vw_asset_mgmt.ops_availability",
"kpiValue": "56.90"
},
{
"kpiName": "vw_asset_mgmt.mttr",
"kpiValue": "98.76"
},
{
"kpiName": "vw_asset_mgmt.total_downtime_hours_wts",
"kpiValue": "760.78"
},
{
"kpiName": "vw_asset_mgmt.unscheduled_downtime_hours_bd_in_ops",
"kpiValue": "0"
},
{
"kpiName": "vw_asset_mgmt.mtbf",
"kpiValue": null
},
{
"kpiName": "vw_asset_mgmt.number_of_breakdowns",
"kpiValue": "106"
},
{
"kpiName": "vw_asset_mgmt.Operational_Running_Hours",
"kpiValue": "435"
}
],
"dimensions": [
{
"dimensionName": "vw_asset_mgmt.month_code",
"dimensionValue": "202503"
},
{
"dimensionName": "vw_asset_mgmt.terminal_code",
"dimensionValue": "PEC2"
}
]
}
]
I attempted to build a console POC application, but I'm not getting the expected hierarchy structure. Could you please review the code below and advise on what I might be doing wrong?
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
public class KpiData
{
public string KpiName { get; set; }
public string KpiValue { get; set; }
}
public class Dimension
{
public string DimensionName { get; set; }
public string DimensionValue { get; set; }
}
public class KpiHierarchy
{
public string DisplayName { get; set; }
public double Value { get; set; }
public Dictionary<string, KpiHierarchy> SubLevels { get; set; } = new Dictionary<string, KpiHierarchy>();
}
public class HierarchyResponse
{
public Dictionary<string, string> Dimensions { get; set; }
public Dictionary<string, KpiHierarchy> Hierarchy { get; set; }
}
public class Relationship
{
public string KpiGroupName { get; set; }
public string ParentKpiName { get; set; }
public string ChildKpiName { get; set; }
public string ParentKpiDisplayName { get; set; }
public string ChildKpiDisplayName { get; set; }
}
public class Program
{
public static void Main()
{
// Sample relationship data
var relationships = new List<Relationship>
{
new Relationship { KpiGroupName = "Operations & Asset Performance", ParentKpiName = "EquipAvailability", ChildKpiName = "total_downtime_hours", ParentKpiDisplayName = "Availability", ChildKpiDisplayName = "Total Downtime" },
new Relationship { KpiGroupName = "Operations & Asset Performance", ParentKpiName = "total_downtime_hours", ChildKpiName = "scheduled_downtime_hours", ParentKpiDisplayName = "Total Downtime", ChildKpiDisplayName = "Scheduled Downtime" },
new Relationship { KpiGroupName = "Operations & Asset Performance", ParentKpiName = "total_downtime_hours", ChildKpiName = "unscheduled_downtime_hours", ParentKpiDisplayName = "Total Downtime", ChildKpiDisplayName = "Unscheduled Downtime" },
new Relationship { KpiGroupName = "Operations & Asset Performance", ParentKpiName = "ops_availability", ChildKpiName = "mttr", ParentKpiDisplayName = "Operational Availability", ChildKpiDisplayName = "MTTR" },
new Relationship { KpiGroupName = "Operations & Asset Performance", ParentKpiName = "ops_availability", ChildKpiName = "mtbf", ParentKpiDisplayName = "Operational Availability", ChildKpiDisplayName = "MTFB" },
new Relationship { KpiGroupName = "Operations & Asset Performance", ParentKpiName = "ops_availability", ChildKpiName = "Operational_Running_Hours", ParentKpiDisplayName = "Operational Availability", ChildKpiDisplayName = "Operational Running Hours" }
};
// Sample input data (actual JSON response)
var actualJson = new List<Dictionary<string, object>> {
new Dictionary<string, object> {
{ "kpIs", new List<Dictionary<string, object>> {
new Dictionary<string, object> { { "kpiName", "vw_asset_mgmt.EquipAvailability" }, { "kpiValue", "98.5" } },
new Dictionary<string, object> { { "kpiName", "vw_asset_mgmt.total_downtime_hours" }, { "kpiValue", "120.5" } },
new Dictionary<string, object> { { "kpiName", "vw_asset_mgmt.scheduled_downtime_hours" }, { "kpiValue", "50.0" } },
new Dictionary<string, object> { { "kpiName", "vw_asset_mgmt.unscheduled_downtime_hours" }, { "kpiValue", "70.5" } },
new Dictionary<string, object> { { "kpiName", "vw_asset_mgmt.ops_availability" }, { "kpiValue", "95.0" } },
new Dictionary<string, object> { { "kpiName", "vw_asset_mgmt.mttr" }, { "kpiValue", "1.5" } },
new Dictionary<string, object> { { "kpiName", "vw_asset_mgmt.total_downtime_hours_wts" }, { "kpiValue", "110.0" } },
new Dictionary<string, object> { { "kpiName", "vw_asset_mgmt.unscheduled_downtime_hours_bd_in_ops" }, { "kpiValue", "0.0" } },
new Dictionary<string, object> { { "kpiName", "vw_asset_mgmt.mtbf" }, { "kpiValue", "500.0" } },
new Dictionary<string, object> { { "kpiName", "vw_asset_mgmt.number_of_breakdowns" }, { "kpiValue", "5" } },
new Dictionary<string, object> { { "kpiName", "vw_asset_mgmt.Operational_Running_Hours" }, { "kpiValue", "4000.0" } }
}},
{ "dimensions", new List<Dictionary<string, object>> {
new Dictionary<string, object> { { "dimensionName", "vw_asset_mgmt.month_code" }, { "dimensionValue", "202503" } },
new Dictionary<string, object> { { "dimensionName", "vw_asset_mgmt.terminal_code" }, { "dimensionValue", "T001" } }
}}
}
};
// Transform the data to hierarchical format
var result = TransformJsonToHierarchy(actualJson, relationships);
// Serialize the result into JSON and print it
var jsonResult = JsonConvert.SerializeObject(result, Formatting.Indented);
Console.WriteLine(jsonResult);
}
public static List<HierarchyResponse> TransformJsonToHierarchy(List<Dictionary<string, object>> actualJson, List<Relationship> relationships)
{
var hierarchyResponses = new List<HierarchyResponse>();
foreach (var jsonItem in actualJson)
{
var kpIs = jsonItem["kpIs"] as List<Dictionary<string, object>>;
var dimensions = jsonItem["dimensions"] as List<Dictionary<string, object>>;
// Build the Dimensions dictionary
var dimensionDict = dimensions.ToDictionary(d => d["dimensionName"].ToString(), d => d["dimensionValue"].ToString());
// Initialize the hierarchy structure
var hierarchy = new Dictionary<string, KpiHierarchy>();
// Process the KPIs and organize them into the hierarchy
foreach (var kpi in kpIs)
{
string kpiName = kpi["kpiName"].ToString().Split('.').Last(); // Use only the last part of the kpi name
double kpiValue = double.TryParse(kpi["kpiValue"]?.ToString(), out double value) ? value : 0;
// Find the relationship for the current KPI
var relationship = relationships.FirstOrDefault(r => kpiName.Equals(r.ChildKpiName));
if (relationship != null)
{
// Ensure parent exists in hierarchy
if (!hierarchy.ContainsKey(relationship.ParentKpiName))
{
hierarchy[relationship.ParentKpiName] = new KpiHierarchy
{
DisplayName = relationship.ParentKpiDisplayName,
Value = 0, // This will be replaced later with the actual value
SubLevels = new Dictionary<string, KpiHierarchy>()
};
}
var parentKpi = hierarchy[relationship.ParentKpiName];
// Add the child KPI to its parent
parentKpi.SubLevels[relationship.ChildKpiName] = new KpiHierarchy
{
DisplayName = relationship.ChildKpiDisplayName,
Value = kpiValue
};
}
}
// Add group name to the hierarchy
var response = new HierarchyResponse
{
Dimensions = dimensionDict,
Hierarchy = new Dictionary<string, KpiHierarchy>
{
{ "group_name", new KpiHierarchy { DisplayName = "Operations & Asset Performance", Value = 0 } }
}
};
response.Hierarchy = hierarchy;
hierarchyResponses.Add(response);
}
return hierarchyResponses;
}
}
Updated POC Sample Application Code:
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
public class KPI
{
public string KpiName { get; set; }
public string KpiValue { get; set; }
}
public class Dimension
{
public string DimensionName { get; set; }
public string DimensionValue { get; set; }
}
public class KpiHierarchy
{
public string DisplayName { get; set; }
public double Value { get; set; }
public Dictionary<string, KpiHierarchy> SubLevels { get; set; } = new Dictionary<string, KpiHierarchy>();
}
public class HierarchyResponse
{
public Dictionary<string, string> Dimensions { get; set; }
public Dictionary<string, KpiHierarchy> Hierarchy { get; set; }
}
public class Relationship
{
public string KpiGroupName { get; set; }
public string ParentKpiName { get; set; }
public string ChildKpiName { get; set; }
public string ParentKpiDisplayName { get; set; }
public string ChildKpiDisplayName { get; set; }
}
public class AssetManagementData
{
public List<KPI> KpIs { get; set; }
public List<Dimension> Dimensions { get; set; }
}
public class Program
{
public static void Main()
{
// Sample relationship data
var relationships = new List<Relationship>
{
new Relationship { KpiGroupName = "Operations & Asset Performance", ParentKpiName = "EquipAvailability", ChildKpiName = "total_downtime_hours", ParentKpiDisplayName = "Availability", ChildKpiDisplayName = "Total Downtime" },
new Relationship { KpiGroupName = "Operations & Asset Performance", ParentKpiName = "total_downtime_hours", ChildKpiName = "scheduled_downtime_hours", ParentKpiDisplayName = "Total Downtime", ChildKpiDisplayName = "Scheduled Downtime" },
new Relationship { KpiGroupName = "Operations & Asset Performance", ParentKpiName = "total_downtime_hours", ChildKpiName = "unscheduled_downtime_hours", ParentKpiDisplayName = "Total Downtime", ChildKpiDisplayName = "Unscheduled Downtime" },
new Relationship { KpiGroupName = "Operations & Asset Performance", ParentKpiName = "ops_availability", ChildKpiName = "mttr", ParentKpiDisplayName = "Operational Availability", ChildKpiDisplayName = "MTTR" }
};
var data = new List<AssetManagementData>
{
new AssetManagementData
{
KpIs = new List<KPI>
{
new KPI { KpiName = "vw_asset_mgmt.EquipAvailability", KpiValue = "100" },
new KPI { KpiName = "vw_asset_mgmt.total_downtime_hours", KpiValue = "980" },
new KPI { KpiName = "vw_asset_mgmt.scheduled_downtime_hours", KpiValue = "450" },
new KPI { KpiName = "vw_asset_mgmt.unscheduled_downtime_hours", KpiValue = "90" },
new KPI { KpiName = "vw_asset_mgmt.ops_availability", KpiValue = "96" },
new KPI { KpiName = "vw_asset_mgmt.mttr", KpiValue = "980" },
},
Dimensions = new List<Dimension>
{
new Dimension { DimensionName = "vw_asset_mgmt.month_code", DimensionValue = "202502" },
new Dimension { DimensionName = "vw_asset_mgmt.terminal_code", DimensionValue = "PEC2" }
}
},
new AssetManagementData
{
KpIs = new List<KPI>
{
new KPI { KpiName = "vw_asset_mgmt.EquipAvailability", KpiValue = "100" },
new KPI { KpiName = "vw_asset_mgmt.total_downtime_hours", KpiValue = "98" },
new KPI { KpiName = "vw_asset_mgmt.scheduled_downtime_hours", KpiValue = "877" },
new KPI { KpiName = "vw_asset_mgmt.unscheduled_downtime_hours", KpiValue = "656" },
new KPI { KpiName = "vw_asset_mgmt.ops_availability", KpiValue = "56.90" },
new KPI { KpiName = "vw_asset_mgmt.mttr", KpiValue = "98.76" }
},
Dimensions = new List<Dimension>
{
new Dimension { DimensionName = "vw_asset_mgmt.month_code", DimensionValue = "202503" },
new Dimension { DimensionName = "vw_asset_mgmt.terminal_code", DimensionValue = "PEC2" }
}
}
};
// Convert the data to a dictionary format
var jsonData = data.Select(item => new Dictionary<string, object>
{
{ "kpIs", item.KpIs.Select(k => new Dictionary<string, object>
{
{ "kpiName", k.KpiName },
{ "kpiValue", k.KpiValue }
}).ToList() },
{ "dimensions", item.Dimensions.Select(d => new Dictionary<string, object>
{
{ "dimensionName", d.DimensionName },
{ "dimensionValue", d.DimensionValue }
}).ToList() }
}).ToList();
// Transform the data to hierarchical format
var result = TransformJsonToHierarchy(jsonData, relationships);
// Serialize the result into JSON and print it
var jsonResult = JsonConvert.SerializeObject(result, Formatting.Indented);
Console.WriteLine(jsonResult);
}
public static List<HierarchyResponse> TransformJsonToHierarchy(List<Dictionary<string, object>> actualJson, List<Relationship> relationships)
{
var hierarchyResponses = new List<HierarchyResponse>();
foreach (var jsonItem in actualJson)
{
var kpIs = jsonItem["kpIs"] as List<Dictionary<string, object>>;
var dimensions = jsonItem["dimensions"] as List<Dictionary<string, object>>;
// Build the Dimensions dictionary
var dimensionDict = dimensions.ToDictionary(d => d["dimensionName"].ToString(), d => d["dimensionValue"].ToString());
// Initialize the hierarchy structure
var hierarchy = new Dictionary<string, KpiHierarchy>();
// Process the KPIs and organize them into the hierarchy
foreach (var kpi in kpIs)
{
string kpiName = kpi["kpiName"].ToString().Split('.').Last(); // Use only the last part of the kpi name
double kpiValue = double.TryParse(kpi["kpiValue"]?.ToString(), out double value) ? value : 0;
// Find the relationship for the current KPI
var relationship = relationships.FirstOrDefault(r => kpiName.Equals(r.ChildKpiName));
if (relationship != null)
{
// Ensure parent exists in hierarchy
if (!hierarchy.ContainsKey(relationship.ParentKpiName))
{
hierarchy[relationship.ParentKpiName] = new KpiHierarchy
{
DisplayName = relationship.ParentKpiDisplayName,
Value = 0, // This will be replaced later with the actual value
SubLevels = new Dictionary<string, KpiHierarchy>()
};
}
var parentKpi = hierarchy[relationship.ParentKpiName];
// Add the child KPI to its parent
parentKpi.SubLevels[relationship.ChildKpiName] = new KpiHierarchy
{
DisplayName = relationship.ChildKpiDisplayName,
Value = kpiValue
};
}
}
// Add group name to the hierarchy
var response = new HierarchyResponse
{
Dimensions = dimensionDict,
Hierarchy = hierarchy
};
hierarchyResponses.Add(response);
}
return hierarchyResponses;
}
}
