go语言的结构体与json字符串格式转换你会了吗?
对于结构体大家都很熟悉,是一种自定义类型,可以将不同类型的同属于这个类的属性(成员变量)集合在一起,换句话说这些成员变量属于键值对,那么这种也就是常见的json格式,我们来看下如何将结构体转成json格式的字符串。
json.Marshal转字符串
package main
import (
"encoding/json"
"fmt"
)
type Person struct {
Name string
Tall float32
Hobby string
}
func main() {
//实例化的时候要注意,最后的逗号不能省略
p := Person{
Name: "Tony", Tall: 173.5, Hobby: "Reading",
}
fmt.Println(p) //{Tony 173.5 Reading}
json_p, err := json.Marshal(p)
fmt.Printf("%T,%s,%v", string(json_p), string(json_p), err)
//string,{"Name":"Tony","Tall":173.5,"Hobby":"Reading"},<nil>
}
如果结构体成员变量名称的首字母是小写的话,会发生什么情况?
package main
import (
"encoding/json"
"fmt"
)
type Person struct {
Name string
Tall float32
Hobby string
address string //首字母小写
Sex string
}
func main() {
//实例化的时候要注意,最后的逗号不能省略
p := Person{
Name: "Tony", Tall: 173.5, Hobby: "Reading", address: "湖南省", Sex: "男",
}
fmt.Println(p) //{Tony 173.5 Reading 湖南省 男}
json_p, err := json.Marshal(p)
fmt.Printf("%T,%s,%v", string(json_p), string(json_p), err)
//string,{"Name":"Tony","Tall":173.5,"Hobby":"Reading","Sex":"男"},<nil>
}
我们发现这个address成员变量没有转换成功,没有出现,那说明如果需要转成json,首字母必须大写。然后我们反过来将json字符串转换成结构体,看下有什么变化。
var out Person
json.Unmarshal(json_p, &out)
fmt.Printf("%T,%#v,%v", out, out, err)
//main.Person,main.Person{Name:"Tony", Tall:173.5, Hobby:"Reading", address:"", Sex:"男"},<nil>
address的内容是空,如果是整型,内容是0,这验证了,如果外部需获取成员变量的情况,首字母需大写。
结构体嵌套
结构体是多个类型的集合,所以除了基本类型之外,自定义类型肯定也是可以一起放在里面,无差别对待使用,而结构体里面的结构体可以是指针也可以不是指针,不过建议使用指针的表示形式,这个只是一个内存地址而已,效率要快。
package main
import (
"encoding/json"
"fmt"
)
type Person struct {
Name string
Tall float32
Hobby string
address string //首字母小写
Sex string
Game *Game //指向一个玩过什么游戏的一个结构体,也可以不使用指针,指针要快
}
type Game struct {
Name1 string
Name2 string
}
func main() {
//实例化的时候要注意,最后的逗号不能省略
p := Person{
Name: "Tony", Tall: 173.5, Hobby: "Reading", address: "湖南省", Sex: "男",
}
//指针用法
game := new(Game)
game.Name1 = "星际争霸"
game.Name2 = "王者荣耀"
p.Game = game
/*
非指针用法
game := Game{Name1: "王者荣耀", Name2: "魔兽世界"}
p.Game = game
*/
json_p, err := json.Marshal(p)
if err != nil {
fmt.Println("转换json字符串失败!")
}
fmt.Printf("%T,%s", string(json_p), string(json_p))
}
//string,{"Name":"Tony","Tall":173.5,"Hobby":"Reading","Sex":"男","Game":{"Name1":"星际争霸","Name2":"王者荣耀"}}
结构体接口
看过Go语言进阶,interface接口,socket套接字这篇文章的伙伴就应该知道,其中的 tester = p 就是将类型赋值给了接口。我们现在来改造这个结构体,使其变得更加的通用,也就是说不管什么类型都可以,而不是指定了string就只能是字符串类型。
type Person struct {
Name interface{}
Tall interface{}
Hobby interface{}
address interface{} //首字母小写
Sex interface{}
Game interface{}
}
然后我们将那个Hobby爱好,原来是字符串的,我们使用整型为其赋值,试下:
p := Person{
Name: "Tony", Tall: 173.5, Hobby: 123, address: "湖南省", Sex: "男",
}
//string,{"Name":"Tony","Tall":173.5,"Hobby":123,"Sex":"男","Game":{"Name1":"星际争霸","Name2":"王者荣耀"}}
OK,没有问题!
所有类型全部替换成interface{}空接口,因为在go语言中的每一种类型都实现了该接口,换句话说就是任何其他类型的数据都可以赋值给interface{}类型
Unmarshal字符串转结构体
json字符串转化成结构体的话,关键是json的字符串格式要严格符合规范,如:双引号需要反斜杠进行转义操作,括号要匹配不能缺失等。Unmarshal两个参数,一个是字节数组,另一个对空结构体取地址即可。
package main
import (
"encoding/json"
"fmt"
)
type Person struct {
Name interface{}
Tall interface{}
Hobby interface{}
address interface{} //首字母小写
Sex interface{}
Game interface{}
}
func main() {
data := "{\"Name\":\"Tony\",\"Tall\":173.5,\"Hobby\":\"Reading\",\"Sex\":\"男\",\"Game\":{\"Name1\":\"星际争霸\",\"Name2\":\"王者荣耀\"}}"
s := []byte(data)
p := Person{}
err := json.Unmarshal(s, &p)
if err != nil {
fmt.Println(err)
}
fmt.Printf("%T,%#v", p, p)
}
/*
main.Person,main.Person{Name:"Tony", Tall:173.5, Hobby:"Reading", address:interface {}(nil), Sex:"男", Game:map[string]interface {}{"Name1":"星际争霸", "Name2":"王者荣耀"}}
*/
我们通过反射看下它们各自的数据类型:
package main
import (
"encoding/json"
"fmt"
"reflect"
)
type Person struct {
Name interface{}
Tall interface{}
Hobby interface{}
address interface{} //首字母小写
Sex interface{}
Game interface{}
}
func main() {
data := "{\"Name\":\"Tony\",\"Tall\":173.5,\"Hobby\":\"Reading\",\"Sex\":\"男\",\"Game\":{\"Name1\":\"星际争霸\",\"Name2\":\"王者荣耀\"}}"
s := []byte(data)
p := Person{}
printType(&p)
err := json.Unmarshal(s, &p)
if err != nil {
fmt.Println(err)
}
fmt.Println("Unmarshal之后的结果")
printType(&p)
}
func printType(p *Person) {
nameType := reflect.TypeOf(p.Name)
tallType := reflect.TypeOf(p.Tall)
hobbyType := reflect.TypeOf(p.Hobby)
addressType := reflect.TypeOf(p.address)
sexType := reflect.TypeOf(p.Sex)
gameType := reflect.TypeOf(p.Game)
fmt.Println("nameType:", nameType)
fmt.Println("ageType:", tallType)
fmt.Println("highType:", hobbyType)
fmt.Println("sexType:", addressType)
fmt.Println("classType:", sexType)
fmt.Println("testType:", gameType)
}
/*
nameType: <nil>
ageType: <nil>
highType: <nil>
sexType: <nil>
classType: <nil>
testType: <nil>
Unmarshal之后的结果
nameType: string
ageType: float64
highType: string
sexType: <nil>
classType: string
testType: map[string]interface {}
*/
最后还可以指定别名,大家可以试下:
Name string `json:"name"`
这个就是用name代替Name
期待您的加入,畅所欲言的交流,一起成长为go语言技术达人
相关推荐
Go 结构体、数组、字典和 json 字符串的相互转换方法
今天小编就为大家分享一篇Go 结构体、数组、字典和 json 字符串的相互转换方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
Go语言时间与JSON序列化:从RFC3339原理到自定义格式实战
在Web开发与API设计中,JSON作为主流数据交换格式,其序列化与反序列化是核心技术环节。时间数据的处理尤为关键,它涉及数据一致性、系统间互操作性和时区管理等基础问题。Go语言标准库encoding/json默认采用RFC3339格式进行时间序列化,这一设计基于国际标准,确保了跨平台和跨语言的数据可读性与无歧义解析。理解其底层实现——通过time.Time类型实现json.Marshaler接口——是掌握自定义格式的基础。在实际工程中,对接不同第三方系统或处理遗留数据时,常需适配多种时间格式,如“2006
GoLand 2026版JSON处理功能深度解析与应用
JSON作为现代软件开发中广泛使用的数据交换格式,其高效处理能力直接影响开发效率。Go语言凭借其简洁的语法和强大的性能,成为处理JSON数据的理想选择。GoLand 2026版本通过智能结构体生成引擎和上下文操作增强,实现了从JSON到Go结构体的无缝转换,自动识别时间格式、自定义类型等特殊字段,显著提升开发效率。这些改进特别适用于API开发、配置管理和测试数据生成等场景,结合omitempty标签和类型推断等特性,为Go开发者提供了更加流畅的JSON处理体验。
Godot引擎与Go语言集成开发指南:GDExtension绑定与高性能游戏开发实践
游戏引擎扩展开发是现代游戏开发中的关键技术,它允许开发者突破引擎原生脚本的限制,引入更强大的编程语言和工具链。其核心原理是通过稳定的应用程序二进制接口(ABI),在引擎运行时加载外部编译的动态链接库,实现跨语言调用与功能扩展。这种技术能显著提升开发效率与运行时性能,尤其在需要处理高并发网络服务、复杂后台逻辑或集成特定技术栈的场景中价值突出。通过GDExtension等标准接口,开发者可以将像Go这类以高并发和简洁语法著称的系统级语言集成到Godot引擎中。本文聚焦于Godot-Go这一具体实践,详细解析了如
go语言结构体转换map、map转换结构体、json字符串转结构体、结构体数据转换到别的结构体
JSON包的妙用,一个函数完成几种数据结构转换方案 1.结构体转map 2.map转结构体 3.结构体数据转移到结构体 4.json字符串转结构体 package main import ( encoding/json fmt reflect ) type User struct { Name string `json:name` Age int `json:age` } func main() { //1、结构体转map user1:=User{} user1.Name=小明 user1.Age=18 mp:=make(map[string


