登录
首页 >  Golang >  Go问答

将嵌套结构展开为 JSON 格式

来源:stackoverflow

时间:2024-02-20 19:33:25 183浏览 收藏

最近发现不少小伙伴都对Golang很感兴趣,所以今天继续给大家介绍Golang相关的知识,本文《将嵌套结构展开为 JSON 格式》主要内容涉及到等等知识点,希望能帮到你!当然如果阅读本文时存在不同想法,可以在评论中表达,但是请勿使用过激的措辞~

问题内容

给定以下结构类型,嵌入在 completestruct 中的 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,这是一个新结构。

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
  }
]

注意:实际上,completestruct 将包含 10 个或更多嵌入结构,每个嵌入结构将包含 10 个或更多字段。所以我想要一个不需要单独输入每个字段的解决方案,我认为这需要使用反射


正确答案


这应该给你你想要的结构:

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

不反思是无法解决的。简单的例子:

func (u *CompleteStruct) MarshalJSON() ([]byte, error) {
    type Result struct {
        Name  string `json:"name"`
        Field string `json:"field"`
        Value any    `json:"value"`
    }
    
    var res []Result
    val := reflect.ValueOf(u).Elem()
    for i := 0; i < val.NumField(); i++ {
        field := val.Field(i)
        switch field.Kind() {
        case reflect.Struct:
            for i := 0; i < field.NumField(); i++ {
                tp := field.Type().Field(i)
                field := field.Field(i)
                res = append(res, Result{
                    Name:  u.Name,
                    Field: tp.Tag.Get("json"),
                    Value: field.Interface(),
                })
            }
        }
    }
    return json.Marshal(res)
}

PLAYGROUND

到这里,我们也就讲完了《将嵌套结构展开为 JSON 格式》的内容了。个人认为,基础知识的学习和巩固,是为了更好的将其运用到项目中,欢迎关注golang学习网公众号,带你了解更多关于的知识点!

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>