pass data from one Struct to another Struct and convert to json

Issue

Hi I have json data which I Unmarshal to machines slice . Now I am looking to copy/append each cluster information, hostname from machines slice struct to Cluster Struct []Cluster and try to populate different values in that struct.

Each machine record has an associated serviceName . I am Looking for the out json format in the desired output below where service_name ,required, vars, value are only passed once even though they are associated with each json record when passed from machine slice.

current Code :

https://go.dev/play/p/6zVRIaLIgdN

Desired output :

{
  "cluster_name": "dev",
  "services": [
    {
      "service_name": "serviceA",
      "required" : true,
      "vars": {
        "common_vars": {
          "user": "custom-user",
          "group": "custom-group"
        }
      },
      "hosts": [
        {
          "host_name": "host1",
          "vars": {
            "common_vars" :{
              "id": 1
            }
          }
        },
        {
          "host_name": "host2",
          "vars": {
            "common_vars":{
              "id": 2
            }
          }
        }

      ]
},
{
"service_name": "serviceB",
"required" : false
 .....
}
      
}
]
}

Current OutPut:
where the ServiceName is repeated with every machine name , I want it to have service_name once in the slice as above output

  "cluster_name": "dev",
  "services": [
    {
      "service_name": "serviceA",
      "required": true,
      "hosts": [
        {
          "host_name": "Machine-1",
          "vars": {
            "common_vars": {
              "id": "1"
            },
            "custom_listeners": {}
          }
        }
      ],
      "vars": {
        "custom_listeners": {}
      }
    },
    {
      **"service_name": "serviceA"**,
      "required": true,
      "hosts": [
        {
          "host_name": "Machine-2",
          "vars": {
            "common_vars": {
              "id": "2"
            },
            "custom_listeners": {}
          }
        }
      ],
      "vars": {
        "custom_listeners": {}
      }
    }
  ]
}

Solution

You have to implement some logic for merging service records with same name.
map[<ServiceName>]<Service> could be used to avoid iterating through slice of services every time.

m := map[string]*Service{}
for i := range machines {
    s, found := m[machines[i].Servicename]
    if !found {
        s = &Service{ServiceName: machines[i].Servicename, Required: true}
        m[machines[i].Servicename] = s
    }
    s.Hosts = append(s.Hosts, Host{HostName: machines[i].Hostname, Vars: Var{CommonVars: map[string]interface{}{"id": machines[i].ID}}})
}
for _, s := range m {
    cService.Services = append(cService.Services, *s)
}

Answered By – medasx

Answer Checked By – David Marino (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.