英文:
How to create the dynamic struct except using interface and Using spread operator
问题
我正在尝试使用Go和Fiber框架创建新的API。我正在使用MongoDB。请参考下面的结构:
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"`
}
Variants字段将包含另一个对象数组。但是字段是动态的,所以我无法定义结构。我使用了[]map[string]string
来解决这个问题。
我的任务是按照以下格式生成CSV文件:
[{
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
}]
只有variants字段会在每一行中改变,其他字段保持不变。我已经创建了除了Variants之外的其他字段。我无法创建结构,因为数据是动态的。
我有很多困惑:
- 如何为动态字段创建结构?
- 如何将Variants展开到根级别?
我来自JavaScript背景,所以我们使用展开运算符。在这里,我对如何在Golang中实现这一点感到困惑。
帮帮我,朋友们!
英文:
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
- How to create the struct for dynamic fields
- 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
答案1
得分: 2
@mkopriva是正确的
但是如果你愿意,你可以使用反射来动态构造一个新的结构体
以下是一个示例:
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"}
英文:
@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"}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论