Home > database >  How to create the dynamic struct except using interface and Using spread operator
How to create the dynamic struct except using interface and Using spread operator

Time:11-11

I am trying to create the new API with Go and Fiber framework. I am using MongoDB. Please refer to my below structure

type Product struct {
    Name           string              `json:"name"`
    Code           string              `json:"code"`
    Description    string              `json:"description"`
    Brand          string              `json:"brand"`
    Variants       []map[string]string `json:"variants"`
    Categories     []int               `json:"categories"`
}

The Variants field will have another set array of objects. But the fields will be dynamic. So I can't define the structure. Now this one I solved with []map[string][string].

My task here I have to form the CSV file with the below format.

[{
    Name: "Rock",
    Code: "RRR"
    Description: "This is rock"
    Brand: "R"
    ...variants
},
{
    Name: "Rock",
    Code: "RRR"
    Description: "This is rock"
    Brand: "R"
    ...variants
},
{
    Name: "Rambo",
    Code: "RAM"
    Description: "This is Rambo"
    Brand: "RA"
    ...variants
},
{
    Name: "Rambo",
    Code: "RAM"
    Description: "This is Rambo"
    Brand: "RA"
    ...variants
}]

Only variants will change for every row. Others will be remaining same I formed the other fields except for the Variants. I can't create the struct because the data will be dynamic.

I have a lot of confusion

  1. How to create the struct for dynamic fields
  2. How to spread the Variants at the root level

I am from javascript. So, we used the spread operator. Here I am confused about how to do that in Golang.

Help me out, guys

CodePudding user response:

@mkopriva is right

However you can use reflection to dynamically construct a new struct if you like

follow is a example:

package main

import (
    "encoding/json"
    "fmt"
    "reflect"
)

type DynamicMap map[string]interface{}

type Product struct {
    Name        string            `json:"name"`
    Code        string            `json:"code"`
    Description string            `json:"description"`
    Brand       string            `json:"brand"`
    Variants    map[string]string `json:"variants"`
    Categories  []int             `json:"categories"`
}

func (j Product) MarshalJSON() ([]byte, error) {
    m := DynamicMap{}
    t := reflect.TypeOf(j)
    v := reflect.ValueOf(j)
    for i := 0; i < t.NumField(); i   {
        if t.Field(i).Tag.Get("json") == "variants" {
            dyn := v.Field(i).Interface().(map[string]string)
            for key, val := range dyn {
                m[key] = val
            }
        } else if t.Field(i).Type.Kind() == reflect.String {
            m[t.Field(i).Tag.Get("json")] = v.Field(i).String()
        } else {
            m[t.Field(i).Tag.Get("json")] = v.Field(i)
        }

    }
    return json.Marshal(m)
}

func (j Product) UnmarshalJSON(data []byte) error {
    fmt.Println("Unmarshal...")
    return json.Unmarshal(data, &j)
}

func main() {
    p := Product{Name: "aa", Variants: map[string]string{"a": "a", "b": "b"}}
    marshal, err := json.Marshal(p)
    if err != nil {
        fmt.Printf("%v\n", err)
    }
    fmt.Printf("%s\n", marshal)
}

{"a":"a","b":"b","brand":"","categories":{},"code":"","description":"","name":"aa"}

  • Related