给定嵌入在CompleteStruct中的以下 struct 类型StructAStructB

type StructA struct {
    A int `json:"a_a"`
    B int `json:"a_b"`
    C int `json:"a_c"`
}
type StructB struct {
    A int `json:"b_a"`
    B int `json:"b_b"`
}

type CompleteStruct struct {
    Name string `json:"name"`
    StructA
    StructB
}

s是一种新的 struct .

s := CompleteStruct{Name: "Example",
    StructA: StructA{
        A: 1, 
        B: 2, 
        C: 3,
    },
    StructB: StructB{
        A: 4,
        B: 5,
    },
}

如何将s转换为下面的json.

[
  {
    "name": "Example",
    "field": "a_a",
    "value": 1
  },
  {
    "name": "Example",
    "field": "a_b",
    "value": 2
  },
  {
    "name": "Example",
    "field": "a_c",
    "value": 3
  },
  {
    "name": "Example",
    "field": "b_a",
    "value": 4
  },
  {
    "name": "Example",
    "field": "b_b",
    "value": 5
  }
]

Note: In reality, 100 will contain 10 or more embedded structs and each embedded struct will contain 10 or more fields. So I would like a solution that does not require typing each field out individually, I assume this will require using reflection

推荐答案

这应该会为您提供所需的 struct :

package main

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

type StructA struct {
    A int `json:"a_a"`
    B int `json:"a_b"`
    C int `json:"a_c"`
}
type StructB struct {
    A int `json:"b_a"`
    B int `json:"b_b"`
}

type CompleteStruct struct {
    Name string `json:"name"`
    StructA
    StructB
}

func main() {
    s := CompleteStruct{Name: "Example",
        StructA: StructA{
            A: 1,
            B: 2,
            C: 3,
        },
        StructB: StructB{
            A: 4,
            B: 5,
        },
    }

    flat(s)

    json.NewEncoder(os.Stdout).Encode(results)
}

type resp struct {
    Name  string `json:"name"`
    Field string `json:"field"`
    Value any    `json:"value"`
}

var globalName string
var results []resp

func flat(s interface{}) {
    st := reflect.TypeOf(s)
    for i := 0; i < st.NumField(); i++ {
        field := st.Field(i)
        if field.Type.Kind() == reflect.Struct {
            flat(reflect.ValueOf(s).Field(i).Interface())
        } else {
            name := field.Tag.Get("json")
            if name == "name" {
                globalName = reflect.ValueOf(s).Field(i).String()
                continue
            }
            results = append(results, resp{Name: globalName, Field: name, Value: reflect.ValueOf(s).Field(i).Interface()})
        }
    }
}
go run ./main.go | jq '.'

Go Playground

Go相关问答推荐

Pulumi-S3-当策略依赖于访问点时,如何将AccesspintPolicy附加到访问点

如何使用Gorilla WebSockets实现Http.Hijacker&;alexedwards/scs/v2

Golang使用Run()执行的命令没有返回

什么东西逃到了堆里?

为什么 `go mod` 占用了另一个磁盘上的空间而不是我的 GOPATH?

无法在go中为docker容器写入有效的挂载路径

Golang chromedp Dockerfile

使用Goldmark在golang中添加ChildNode会导致堆栈溢出

杜松子wine 和中间件

是否可以在 hyperledger-chaincode 中使用 gRPC?如果可以,我如何避免在测试网络上调用时出错?

使用 unsafe.Pointer 将 struct point直接转换为另一个 struct 是否安全?

Go 的垃圾收集器在使用时删除 ZeroMQ 套接字

使用 os/exec 和在命令行执行之间的结果莫名其妙地不同

在删除级联时无法在 Gorm 中按预期工作

如何在 GORM 中获取字段值

如何在循环中旋转图像以便在 golang 中创建 GIF?

gqlgen go,通过添加一个解析器来减少数据库调用

手动下载并放置一个 golang mod 文件

如何在 Prometheus 中正确检测区域和环境信息?

在 Go 泛型中,如何对联合约束中的类型使用通用方法?