一、包简介

        mapstructure用于将通用的map[string]interface{}解码到对应的 Go 结构体中,或者执行相反的操作。很多时候,解析来自多种源头的数据流时,我们一般事先并不知道他们对应的具体类型。只有读取到一些字段之后才能做出判断。这时,我们可以先使用标准的encoding/json库将数据解码为map[string]interface{}类型,然后根据标识字段利用mapstructure库转为相应的 Go 结构体以便使用.

二、安装

  1. #不能下载可以设置goproxy
  2. go get github.com/mitchellh/mapstructure

https://pkg.go.dev/github.com/mitchellh/mapstructure

三、介绍

解码:

  1. 解码采用输入结构并使用反射将其转换为输出结构。输出必须是指向mapstruct的指针。
  1. type Person struct {
  2. Name string
  3. Age int
  4. Emails []string
  5. Extra map[string]string
  6. }
  7. // 此输入可以来自任何地方,但通常来自解码 JSON 之类的东西,我们最初不太确定结构。
  8. input := map[string]interface{}{
  9. "name": "Mitchell",
  10. "age": 91,
  11. "emails": []string{"one", "two", "three"},
  12. "extra": map[string]string{
  13. "twitter": "mitchellh",
  14. },
  15. }
  16. var result Person
  17. //解码
  18. err := Decode(input, &result)
  19. if err != nil {
  20. panic(err)
  21. }
  22. fmt.Printf("%#v", result)

嵌套结构体

  1. // 允许使用 squash 标签压缩多个嵌入式结构。这是通过创建多种类型的复合结构并解码到其中来演示的。在这种情况下,一个人可以随身携带Family和Location,以及他们自己的Name。
  2. type Family struct {
  3. LastName string
  4. }
  5. type Location struct {
  6. City string
  7. }
  8. type Person struct {
  9. Family `mapstructure:",squash"`
  10. Location `mapstructure:",squash"`
  11. FirstName string
  12. }
  13. input := map[string]interface{}{
  14. "FirstName": "Mitchell",
  15. "LastName": "Hashimoto",
  16. "City": "San Francisco",
  17. }
  18. var result Person
  19. err := Decode(input, &result)
  20. if err != nil {
  21. panic(err)
  22. }
  23. fmt.Printf("%s %s, %s", result.FirstName, result.LastName, result.City)

元数据

  1. type Person struct {
  2. Name string
  3. Age int
  4. }
  5. // 此输入可以来自任何地方,但通常来自解码 JSON 之类的东西,我们最初不太确定结构。
  6. input := map[string]interface{}{
  7. "name": "Mitchell",
  8. "age": 91,
  9. "email": "foo@bar.com",
  10. }
  11. // 对于元数据,我们制作了一个更高级的解码器配置,以便我们可以更精细地配置所使用的解码器。在这种情况下,我们只是告诉解码器我们要跟踪元数据。
  12. var md Metadata
  13. var result Person
  14. config := &DecoderConfig{
  15. Metadata: &md,
  16. Result: &result,
  17. }
  18. decoder, err := NewDecoder(config)
  19. if err != nil {
  20. panic(err)
  21. }
  22. if err := decoder.Decode(input); err != nil {
  23. panic(err)
  24. }
  25. fmt.Printf("Unused keys: %#v", md.Unused)
  26. //运行结果: Unused keys: []string{"email"}
  27. //email没有使用,可以查看Metadata结构体的其他字段解锁更多功能

添加省略空值的注释

  1. // 添加省略空注释以避免空值的映射键
  2. type Family struct {
  3. LastName string
  4. }
  5. type Location struct {
  6. City string
  7. }
  8. type Person struct {
  9. *Family `mapstructure:",omitempty"`
  10. *Location `mapstructure:",omitempty"`
  11. Age int
  12. FirstName string
  13. }
  14. result := &map[string]interface{}{}
  15. input := Person{FirstName: "Somebody"}
  16. err := Decode(input, &result)
  17. if err != nil {
  18. panic(err)
  19. }
  20. fmt.Printf("%+v", result)

未知的数据可以放在具有”,remain”标签的 map[string]interface{},字段下,该字段必须是map[string]interface{}类型

  1. // 请注意,结构类型中定义的映射结构标记可以指示值映射到哪些字段。
  2. type Person struct {
  3. Name string
  4. Age int
  5. Other map[string]interface{} `mapstructure:",remain"`
  6. }
  7. input := map[string]interface{}{
  8. "name": "Mitchell",
  9. "age": 91,
  10. "email": "mitchell@example.com",
  11. }
  12. var result Person
  13. err := Decode(input, &result)
  14. if err != nil {
  15. panic(err)
  16. }
  17. fmt.Printf("%#v", result)

tag,类似json解析的重命名

  1. // 请注意,结构类型中定义的映射结构标记可以指示值映射到哪些字段。
  2. type Person struct {
  3. Name string `mapstructure:"person_name"`
  4. Age int `mapstructure:"person_age"`
  5. }
  6. input := map[string]interface{}{
  7. "person_name": "Mitchell",
  8. "person_age": 91,
  9. }
  10. var result Person
  11. err := Decode(input, &result)
  12. if err != nil {
  13. panic(err)
  14. }
  15. fmt.Printf("%#v", result)

弱类型语言数据的处理

  1. type Person struct {
  2. Name string
  3. Age int
  4. Emails []string
  5. }
  6. // 该输入可以来自任何地方,但通常来自解码JSON,该json由弱类型的语言(例如PHP)生成。
  7. input := map[string]interface{}{
  8. "name": 123, // number => string
  9. "age": "42", // string => number
  10. "emails": map[string]interface{}{}, // empty map => empty array
  11. }
  12. var result Person
  13. config := &DecoderConfig{
  14. WeaklyTypedInput: true,
  15. Result: &result,
  16. }
  17. decoder, err := NewDecoder(config)
  18. if err != nil {
  19. panic(err)
  20. }
  21. err = decoder.Decode(input)
  22. if err != nil {
  23. panic(err)
  24. }
  25. fmt.Printf("%#v", result)
  26. //也可使用weakdecode函数

其他函数见文档

文档更新时间: 2022-12-09 17:27   作者:张尚