详解Go语言中结构体与JSON间的转换

作者:陈明勇 时间:2024-04-28 09:10:50 

前言

在日常开发中,我们往往会将 JSON 解析成对应的结构体,反之也会将结构体转成 JSON。接下来本文会通过 JSON 包的两个函数,来介绍 JSON 与结构体之间的转换。

结构体转 JSON

Marshal(v any) ([]byte, error):将 v 转成 JSON 数据,以 []byte 的形式返回。

import (
   "encoding/json"
   "fmt"
)

type User struct {
   Name           string
   Age            int
   Height         float64
   Weight         *float64
   Child          bool
   marriageStatus string
}

func main() {
   weight := 120.5
   user := User{
       Name:           "gopher",
       Age:            18,
       Height:         180.5,
       Weight:         &weight,
       Child:          false,
       marriageStatus: "未婚",
   }
   jsonBytes, err := json.Marshal(user)
   if err != nil {
       fmt.Println("error: ", err)
       return
   }
   fmt.Println(string(jsonBytes)) // {"Name":"gopher","Age":18,"Height":180.5,"Weight":120.5,"Child":false}
}

执行结果:

{"Name":"gopher","Age":18,"Height":180.5,"Weight":120.5,"Child":false}

根据结果可知:

  • 不可导出字段(字段名以小写字母开头),是不能被转成 JSONkey 的,这也符合 Go 的语法规定,以小写字母开头的变量或结构体字段等,不能在包外被访问。

  • 转换后的字段名,与结构体字段的名字一样。

  • 如果字段是指针类型,转换后的值为指针指向的字段值。

如果我们想要指定字段转换之后的命名,或者将一个可导出的字段进行忽略,可以通过给结构体字段打上 JSON 标签的方式实现。

import (
   "encoding/json"
   "fmt"
)

type User struct {
   Name           string   `json:"name"`
   Age            int      `json:"age"`
   Height         float64  `json:"height"`
   Weight         *float64 `json:"weight"`
   Child          bool     `json:"child"`
   MarriageStatus string   `json:"-"`
}

func main() {
   weight := 120.5
   user := User{
       Name:           "gopher",
       Age:            18,
       Height:         180.5,
       Weight:         &weight,
       Child:          false,
       MarriageStatus: "未婚",
   }
   jsonBytes, err := json.Marshal(user)
   if err != nil {
       fmt.Println("error: ", err)
       return
   }
   fmt.Println(string(jsonBytes)) // {"name":"gopher","age":18,"height":180.5,"weight":120.5,"child":false}
}

通过给结构体字段定打上 JSON 标签,可指定转成 JSON 后的字段名,如果 JSON 标签的值为 -,则在转换 JSON 时忽略此字段。

JSON 解析结构体

Unmarshal(data []byte, v any) error:将 JSON 解析成指定的结构体。

import (
   "encoding/json"
   "fmt"
)

type User struct {
   Name           string  `json:"name"`
   Age            int     `json:"age"`
   Height         float64 `json:"height"`
   Child          bool    `json:"-"`
   marriageStatus string
}

func main() {
   userStr := `
   {
     "name": "gopher",
     "age": 18,
     "height": 180.5,
     "child": true,
     "marriageStatus": "未婚"
   }
   `
   user := &User{}
   err := json.Unmarshal([]byte(userStr), &user)
   if err != nil {
       fmt.Println("error: ", err)
       return
   }
   fmt.Printf("%#v", user) // &main.User{Name:"gopher", Age:18, Height:180.5, Child:false, marriageStatus:""}
}

执行结果:

&main.User{Name:"gopher", Age:18, Height:180.5, Child:false, marriageStatus:""}

根据结果可知:

使用Unmarshal函数时,我们需要传入结构体的指针类型,否则结构体字段的值将不会被改变,因为底层是通过指针去修改结构体字段的值。

JSON 解析时,JSONkey 与结构体字段的匹配规则是:

  • 优先查找 JSON 标签值和 key 一样的,找到则将 value 赋值给对应字段。

  • 如果没有 JSON 标签值与 key 相匹配,则根据字段名进行匹配。

可以发现,如果结构体字段是非导出字段或 JSON 标签的值为 -,将不会被匹配到。

小结

本文介绍了 Go 语言里,JSON 与结构体之间的转换。在结构体转 JSON 时,我们可以通过给字段打标签,指定转换后的 key 命名,需要注意的是,如果结构体的字段为非导出字段或字段的 JSON 标签值为 -,在转换 JSON 时,将会被忽略。反之 JSON 解析结构体时也是一样的。

来源:https://juejin.cn/post/7176291854621605945

标签:Go语言,结构体,JSON
0
投稿

猜你喜欢

  • Python 查看list中是否含有某元素的方法

    2023-07-29 21:46:08
  • python使用urlparse分析网址中域名的方法

    2022-12-06 01:00:59
  • 解决django xadmin主题不显示和只显示bootstrap2的问题

    2022-11-24 14:41:56
  • 基于一致性hash算法(consistent hashing)的使用详解

    2024-01-25 02:30:02
  • 解决Keras 中加入lambda层无法正常载入模型问题

    2022-02-21 03:41:11
  • Javascript+XMLHttpRequest+asp.net无刷新读取数据库数据

    2024-01-17 17:32:18
  • Mysql子查询IN中使用LIMIT应用示例

    2024-01-27 01:44:17
  • keras:model.compile损失函数的用法

    2023-11-23 08:44:21
  • 在MySQL中用正则表达式替换数据库中的内容的方法

    2024-01-17 02:51:57
  • 使用Nginx+uWsgi实现Python的Django框架站点动静分离

    2023-11-13 11:30:37
  • 5个CSS3技术实现设计增强

    2009-09-04 17:04:00
  • 常用正则表达式例子及评注说明

    2008-01-03 13:04:00
  • Golang Gin 中间件 Next()方法示例详解

    2024-02-20 07:29:22
  • 解析ajax事件的调用顺序

    2023-11-21 18:12:56
  • 使用Windows批处理和WMI设置Python的环境变量方法

    2023-07-28 23:07:37
  • PHP删除数组中空值的方法介绍

    2023-11-24 03:04:19
  • Django集成MongoDB实现过程解析

    2022-07-10 03:32:35
  • asp.net下利用js实现返回上一页的实现方法小集

    2024-05-28 15:37:22
  • 使用Abot中文分词组件来开发ASP站内搜索引擎

    2007-10-18 13:36:00
  • 12种实现301网页重定向方法的代码实例(含Web编程语言和Web服务器)

    2023-08-22 23:27:30
  • asp之家 网络编程 m.aspxhome.com