如何在golang中正确地循环两个嵌套的json结构?



我是新手。我有2个相同的json嵌套结构,每个结构都填充了2个api调用的输出。一个调用获取cpu和另一个内存指标。我可以单独解组它们,并打印出项目名称和cpu和内存的值,尽管在2个单独的代码块中。我遇到的问题是,我想在同一行上打印出cpu和内存指标,旁边是他们的项目名称。

这是我用来打印项目的CPU指标的代码。它创建了一个漂亮的CSV格式输出:

// CPU Metrics
// Loop through the data for the Month, Project, CPU requests, and CPU Usage
fmt.Println("Month, Project, CPU Request(Core hours), CPU Usage(Core hours)n")
for _, value_cpu := range rh_values_cpu.Data {
for _, val_cpu := range value_cpu.Projects {
str := val_cpu.Project
s := strings.Contains(str, "openshift")
if s == true  {
continue
}
fmt.Printf("%s, %s, ", value_cpu.Date, val_cpu.Project)
for _, v_cpu := range val_cpu.Values {
fmt.Printf("%.1f, %.1fn", v_cpu.Request.Value, v_cpu.Usage.Value)
}
}
}

我有类似的代码内存指标也工作得很好。

下面是我用来循环两个json结构的代码。我怀疑我没有正确地使用嵌套循环,或者需要以不同的方式解决问题。

// CPU & Memory Metrics
// Loop through the data for the Month, Project, CPU requests, CPU Usage, Memory requests, and Memory Usage
fmt.Println("Month, Project, CPU Request(Core hours), CPU Usage(Core hours) Memory Request(mBytes), Memory Usage(mBytes)n")
for _, value_cpu := range rh_values_cpu.Data {
for _, value_mem := range rh_values_MEM.Data {
for _, val_cpu := range value_cpu.Projects {
for _, val_mem := range value_mem.Projects {
str := val_cpu.Project
s := strings.Contains(str, "openshift")
if s == true  {
continue
}
fmt.Printf("%s, %s, ", value_cpu.Date, val_cpu.Project)
for _, v_cpu := range val_cpu.Values {
fmt.Printf("%.1f, %.1f ", v_cpu.Request.Value, v_cpu.Usage.Value)
for _,v_mem := range val_mem.Values {
fmt.Printf("%.1f, %.1fn", v_mem.Request.Value, v_mem.Usage.Value)
}
}
}
}
}
}

这里有一个json结构:

type RH_Output_MEM struct {
Meta struct {
Count    int    `json:"count"`
Others   int    `json:"others"`
Currency string `json:"currency"`
Filter   struct {
Resolution     string `json:"resolution"`
TimeScopeValue string `json:"time_scope_value"`
TimeScopeUnits string `json:"time_scope_units"`
Limit          int    `json:"limit"`
Offset         int    `json:"offset"`
} `json:"filter"`
GroupBy struct {
Project []string `json:"project"`
} `json:"group_by"`
OrderBy struct {
} `json:"order_by"`
Exclude struct {
} `json:"exclude"`
Total struct {
Usage struct {
Value float64 `json:"value"`
Units string  `json:"units"`
} `json:"usage"`
Request struct {
Value float64 `json:"value"`
Units string  `json:"units"`
} `json:"request"`
Limit struct {
Value float64 `json:"value"`
Units string  `json:"units"`
} `json:"limit"`
Capacity struct {
Value float64 `json:"value"`
Units string  `json:"units"`
} `json:"capacity"`
Infrastructure struct {
Raw struct {
Value float64 `json:"value"`
Units string  `json:"units"`
} `json:"raw"`
Markup struct {
Value float64 `json:"value"`
Units string  `json:"units"`
} `json:"markup"`
Usage struct {
Value float64 `json:"value"`
Units string  `json:"units"`
} `json:"usage"`
Distributed struct {
Value float64 `json:"value"`
Units string  `json:"units"`
} `json:"distributed"`
Total struct {
Value float64 `json:"value"`
Units string  `json:"units"`
} `json:"total"`
} `json:"infrastructure"`
Supplementary struct {
Raw struct {
Value float64 `json:"value"`
Units string  `json:"units"`
} `json:"raw"`
Markup struct {
Value float64 `json:"value"`
Units string  `json:"units"`
} `json:"markup"`
Usage struct {
Value float64 `json:"value"`
Units string  `json:"units"`
} `json:"usage"`
Distributed struct {
Value float64 `json:"value"`
Units string  `json:"units"`
} `json:"distributed"`
Total struct {
Value float64 `json:"value"`
Units string  `json:"units"`
} `json:"total"`
} `json:"supplementary"`
Cost struct {
Raw struct {
Value float64 `json:"value"`
Units string  `json:"units"`
} `json:"raw"`
Markup struct {
Value float64 `json:"value"`
Units string  `json:"units"`
} `json:"markup"`
Usage struct {
Value float64 `json:"value"`
Units string  `json:"units"`
} `json:"usage"`
Distributed struct {
Value float64 `json:"value"`
Units string  `json:"units"`
} `json:"distributed"`
Total struct {
Value float64 `json:"value"`
Units string  `json:"units"`
} `json:"total"`
} `json:"cost"`
} `json:"total"`
} `json:"meta"`
Links struct {
First    string      `json:"first"`
Next     string      `json:"next"`
Previous interface{} `json:"previous"`
Last     string      `json:"last"`
} `json:"links"`
Data []struct {
Date     string `json:"date"`
Projects []struct {
Project string `json:"project"`
Values  []struct {
Date    string `json:"date"`
Project string `json:"project"`
Usage   struct {
Value float64 `json:"value"`
Units string  `json:"units"`
} `json:"usage"`
Request struct {
Value float64 `json:"value"`
Units string  `json:"units"`
} `json:"request"`
Limit struct {
Value float64 `json:"value"`
Units string  `json:"units"`
} `json:"limit"`
Capacity struct {
Value float64 `json:"value"`
Units string  `json:"units"`
} `json:"capacity"`
Classification string   `json:"classification"`
SourceUUID     []string `json:"source_uuid"`
Clusters       []string `json:"clusters"`
Infrastructure struct {
Raw struct {
Value float64 `json:"value"`
Units string  `json:"units"`
} `json:"raw"`
Markup struct {
Value float64 `json:"value"`
Units string  `json:"units"`
} `json:"markup"`
Usage struct {
Value float64 `json:"value"`
Units string  `json:"units"`
} `json:"usage"`
Distributed struct {
Value float64 `json:"value"`
Units string  `json:"units"`
} `json:"distributed"`
Total struct {
Value float64 `json:"value"`
Units string  `json:"units"`
} `json:"total"`
} `json:"infrastructure"`
Supplementary struct {
Raw struct {
Value float64 `json:"value"`
Units string  `json:"units"`
} `json:"raw"`
Markup struct {
Value float64 `json:"value"`
Units string  `json:"units"`
} `json:"markup"`
Usage struct {
Value float64 `json:"value"`
Units string  `json:"units"`
} `json:"usage"`
Distributed struct {
Value float64 `json:"value"`
Units string  `json:"units"`
} `json:"distributed"`
Total struct {
Value float64 `json:"value"`
Units string  `json:"units"`
} `json:"total"`
} `json:"supplementary"`
Cost struct {
Raw struct {
Value float64 `json:"value"`
Units string  `json:"units"`
} `json:"raw"`
Markup struct {
Value float64 `json:"value"`
Units string  `json:"units"`
} `json:"markup"`
Usage struct {
Value float64 `json:"value"`
Units string  `json:"units"`
} `json:"usage"`
Distributed struct {
Value float64 `json:"value"`
Units string  `json:"units"`
} `json:"distributed"`
Total struct {
Value float64 `json:"value"`
Units string  `json:"units"`
} `json:"total"`
} `json:"cost"`
} `json:"values"`
} `json:"projects"`
} `json:"data"`
}

下面是我在运行程序时得到的输出片段。如您所见,Date、Project和内部循环(CPU指标)自身重复,而外部循环(内存指标)运行:

我正在寻找一个输出,其中我每个项目有一行(月,项目,CPU指标,内存指标)

Month, Project, CPU Request(Core hours), CPU Usage(Core hours) Memory Request(mBytes), Memory Usage(mBytes)
2022-12, amq-demo-streams, 0.0, 34.0, 0.0, 4353.2
2022-12, amq-demo-streams, 0.0, 34.0, 1115.6, 1081.4
2022-12, amq-demo-streams, 0.0, 34.0, 0.0, 10675.9
2022-12, amq-demo-streams, 0.0, 34.0, 100.9, 284.0
2022-12, amq-demo-streams, 0.0, 34.0, 0.0, 70064.5
2022-12, amq-demo-streams, 0.0, 34.0, 773088.9, 427757.8
2022-12, amq-demo-streams, 0.0, 34.0, 9440.0, 11610.3
2022-12, amq-demo-streams, 0.0, 34.0, 9471.3, 11696.9
2022-12, amq-demo-streams, 0.0, 34.0, 0.0, 2455.2
2022-12, amq-demo-streams, 0.0, 34.0, 0.0, 3.3
2022-12, amq-demo-streams, 0.0, 34.0, 0.0, 0.0
2022-12, amq-demo-streams, 0.0, 34.0, -0.3, 0.0
2022-12, amq-demo-streams, 0.0, 34.0, 3785.0, 6610.4
2022-12, amq-demo-streams, 0.0, 34.0, 252.3, 1007.8
2022-12, amq-demo-streams, 0.0, 34.0, 757.0, 883.0
2022-12, amq-demo-streams, 0.0, 34.0, 1009.4, 1613.4
2022-12, amq-demo-streams, 0.0, 34.0, 378.5, 413.5
2022-12, amq-demo-streams, 0.0, 34.0, 908.4, 2856.8
2022-12, amq-demo-streams, 0.0, 34.0, 252.3, 248.7
2022-12, amq-demo-streams, 0.0, 34.0, 66873.8, 21035.3
2022-12, amq-demo-streams, 0.0, 34.0, 353.3, 611.9
2022-12, amq-demo-streams, 0.0, 34.0, 10203.6, 12418.3
2022-12, amq-demo-streams, 0.0, 34.0, 504.7, 398.3
2022-12, amq-demo-streams, 0.0, 34.0, 1135.5, 2248.5
2022-12, amq-demo-streams, 0.0, 34.0, 252.3, 610.6
2022-12, amq-demo-streams, 0.0, 34.0, 252.3, 370.6

我允许自己使用更简单的结构体定义。你可以把这些代码应用到你的结构中。

type Cpu struct {
Project string
Data    []Data
}
type Memory struct {
Project string
Data    []Data
}
type Data struct {
Date     string
Projects []Project
}
type Project struct {
Project string
Values  []struct {
Request float64
Value   float64
}
}
func CSVOutput(cpu Cpu, mem Memory) error {
// Returns an error if cpu & memory's data are the same length
if len(cpu.Data) != len(mem.Data) {
return fmt.Errorf("cpu.Data and mem.Data don't have the same length")
}
// Printing CSV file header
fmt.Println("Month, Project, CPU Request(Core hours), CPU Usage(Core hours) Memory Request(mBytes), Memory Usage(mBytes)")
for i := range cpu.Data {
cpuData := cpu.Data[i]
memData := mem.Data[i]
// Using the format from Errorf to add context to the error
if len(cpuData.Projects) != len(memData.Projects) {
return fmt.Errorf("cpu.Data[%d].Projects and mem.Data[%d].Projects don't have the same length", i, i)
}
for j := range cpuData.Projects {
cpuProject := cpuData.Projects[j]
memProject := memData.Projects[j]
if len(cpuProject.Values) != len(memProject.Values) {
return fmt.Errorf("cpu.Data[%d].Projects[%d].Values and mem.Data[%d].Projects[%d].Values don't have the same length", i, j, i, j)
}
name := cpuProject.Project
date := cpuData.Date
// Continue if the cpu project concerns openshift
if strings.Contains(name, "openshift") {
continue
}
for k := range cpuProject.Values {
cpuValue := cpuProject.Values[k]
memValue := memProject.Values[k]
fmt.Printf("%s, %s, %.1f, %.1f, %.1f, %.1f", date, name, cpuValue.Request, cpuValue.Value, memValue.Request, memValue.Value)
}
}
}
return nil
}

此代码仅在接收到与内存数据一样多的cpu数据时有效。
如果不是这样的话,你必须找到一种方法将某个cpu的数据链接到它的内存等效。
如果你认为这种情况可能出现,这个问题可以进一步讨论。

最新更新