前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Go中JSON转换与泛型

Go中JSON转换与泛型

作者头像
码客说
发布2024-03-29 13:07:07
640
发布2024-03-29 13:07:07
举报
文章被收录于专栏:码客码客

查看是否支持泛型

Go语言的泛型支持始于Go 1.18版本。

在这个版本中,Go核心团队进行了自Go语言开源以来最大的一次语法特性变更,引入了对使用参数化类型的泛型代码的支持。

查看版本

代码语言:javascript
复制
go version

在不支持泛型的版本里,泛型编程使用interface{}实现。

简单的JSON转换

代码语言:javascript
复制
package test

import (
	"encoding/json"
	"fmt"
	"z-wiki/utils"
)

type Person struct {
	Name string `json:"name"`
	Age  int    `json:"age"`
}

func Json2Str() {
	person := Person{Name: "Alice", Age: 30}
	jsonData, err := json.Marshal(person)
	if err != nil {
		fmt.Println("转换失败:", err)
		return
	}
	jsonString := string(jsonData)
	fmt.Println("Json2Str:", jsonString)
}

func Str2Json() {
	str := `{"Name": "Alice", "Age": 30}`
	var person Person
	err := json.Unmarshal([]byte(str), &person)
	if err != nil {
		fmt.Println("转换失败:", err)
		return
	}
	fmt.Printf("Str2Json:%+v\n", person)
}

带泛型的JSON转换

代码语言:javascript
复制
package test

import (
	"encoding/json"
	"fmt"
	"z-wiki/utils"
)

type ResultVo[T any] struct {
	Code int    `json:"code"`
	Msg  string `json:"msg"`
	Obj  T      `json:"obj"`
}

type Person struct {
	Name string `json:"name"`
	Age  int    `json:"age"`
}

func Str2Json2() {
	str := `{
			  "code": 0,
			  "msg": "success",
			  "obj": {
				"Name": "Alice",
				"Age": 30
			  }
			}`
	var result ResultVo[Person]
	err := json.Unmarshal([]byte(str), &result)
	if err != nil {
		fmt.Println("转换失败:", err)
		return
	}
	fmt.Printf("Str2Json2:%+v\n", result)
}

JSON转换工具类

工具类

utils/json_utils.go

代码语言:javascript
复制
package utils

import (
	"encoding/json"
)

// ObjToStr 对象转JSON字符串
func ObjToStr(value interface{}) (string, error) {
	meta, err := json.Marshal(value)
	return string(meta), err
}

// StrToObj 字符串转对象
func StrToObj(meta string, result interface{}) error {
	return json.Unmarshal(StringToBytes(meta), result)
}

func StringToBytes(value string) []byte {
	return []byte(value)
}

测试

代码语言:javascript
复制
package test

import (
	"fmt"
	"z-wiki/utils"
)

type ResultVo[T any] struct {
	Code int    `json:"code"`
	Msg  string `json:"msg"`
	Obj  T      `json:"obj"`
}

type Person struct {
	Name string `json:"name"`
	Age  int    `json:"age"`
}

func Obj2Str() {
	result := ResultVo[Person]{Code: 0, Msg: "success", Obj: Person{Name: "Alice", Age: 30}}
	jsonString, err := utils.ObjToStr(result)
	if err != nil {
		return
	}
	fmt.Println("Obj2Str:", jsonString)
}

func Obj2Str2() {
	result := []Person{Person{Name: "张三", Age: 18}, Person{Name: "李四", Age: 30}}
	jsonString, err := utils.ObjToStr(result)
	if err != nil {
		return
	}
	fmt.Println("Obj2Str2:", jsonString)
}

func Str2Obj() {
	str := `{
			  "code": 0,
			  "msg": "success",
			  "obj": {
				"Name": "Alice",
				"Age": 30
			  }
			}`
	var result ResultVo[Person]
	err := utils.StrToObj(str, &result)
	if err != nil {
		return
	}
	fmt.Printf("Str2Obj:%+v\n", result)
}

func Str2Obj2() {
	str := `[
			  {
				"Name": "张三",
				"Age": 30
			  },
			  {
				"Name": "李四",
				"Age": 18
			  }
			]`

	var result []Person
	err := utils.StrToObj(str, &result)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Printf("Str2Obj2:%+v\n", result)
}

JSON转换工具类(泛型)

工具类

代码语言:javascript
复制
package utils

import (
	"encoding/json"
)

// ObjToJson 对象转JSON字符串
func ObjToJson[T any](obj T) (string, error) {
	meta, err := json.Marshal(obj)
	return string(meta), err
}

// JsonToObj 字符串转对象
func JsonToObj[T any](str string) (T, error) {
	var result T
	err := json.Unmarshal(StringToBytes(str), &result)
	return result, err
}

func StringToBytes(str string) []byte {
	return []byte(str)
}

测试

代码语言:javascript
复制
package test

import (
	"fmt"
	"z-wiki/utils"
)

type ResultVo[T any] struct {
	Code int    `json:"code"`
	Msg  string `json:"msg"`
	Obj  T      `json:"obj"`
}

type Person struct {
	Name string `json:"name"`
	Age  int    `json:"age"`
}

func Obj2Str() {
	result := ResultVo[Person]{Code: 0, Msg: "success", Obj: Person{Name: "Alice", Age: 30}}
	jsonString, err := utils.ObjToJson[ResultVo[Person]](result)
	if err != nil {
		return
	}
	fmt.Println("Obj2Str:", jsonString)
}

func Obj2Str2() {
	result := []Person{Person{Name: "张三", Age: 18}, Person{Name: "李四", Age: 30}}
	jsonString, err := utils.ObjToJson[[]Person](result)
	if err != nil {
		return
	}
	fmt.Println("Obj2Str2:", jsonString)
}

func Str2Obj() {
	str := `{
			  "code": 0,
			  "msg": "success",
			  "obj": {
				"Name": "Alice",
				"Age": 30
			  }
			}`
	result, err := utils.JsonToObj[ResultVo[Person]](str)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Printf("Str2Obj:%+v\n", result)
}

func Str2Obj2() {
	str := `[
			  {
				"Name": "张三",
				"Age": 30
			  },
			  {
				"Name": "李四",
				"Age": 18
			  }
			]`

	result, err := utils.JsonToObj[[]Person](str)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Printf("Str2Obj2:%+v\n", result)
}

main_test.go

代码语言:javascript
复制
package test

import (
	"testing"
)

// 普通的测试
func Test01(t *testing.T) {
	Obj2Str()
	Obj2Str2()

	Str2Obj()
	Str2Obj2()
}

两者结合

这里对象转字符串一般不会报错,所以直接返回的字符串,不再返回错误。

对象转字符串不再传入原类型,方便调用。

字符串转对象依旧使用的泛型。

代码语言:javascript
复制
package utils

import (
	"encoding/json"
)

// ObjToJson 对象转JSON字符串
func ObjToJson(value interface{}) string {
	meta, err := json.Marshal(value)
	if err != nil {
		return ""
	}
	return string(meta)
}

// JsonToObj 字符串转对象
func JsonToObj[T any](str string) (T, error) {
	var result T
	err := json.Unmarshal(StringToBytes(str), &result)
	return result, err
}

func StringToBytes(str string) []byte {
	return []byte(str)
}

知识点

interface{}

在 Go 语言中,interface{} 是一种空接口类型(empty interface),也被称为“空接口”。

空接口可以接受任何类型的值,因为它不限制其包含的值的类型。换句话说,空接口不包含任何方法签名,因此可以表示任何类型的值。

在 Go 中,空接口的定义如下:

代码语言:javascript
复制
type emptyInterface interface{}

通过空接口,可以存储任何值,因为任何值都满足空接口的要求。这使得空接口在处理未知类型、泛型编程或者需要接受任意类型参数的情况下非常有用。

下面是一个简单的示例,展示了如何使用空接口来接受任意类型的值:

代码语言:javascript
复制
package main

import "fmt"

func describe(i interface{}) {
    fmt.Printf("(%v, %T)\n", i, i)
}

func main() {
    var i interface{}

    i = 42
    describe(i)

    i = "hello"
    describe(i)

    i = true
    describe(i)
}

在上面的示例中,describe 函数接受一个空接口参数,并打印出该参数的值和类型。

main 函数中,我们使用不同类型的值调用 describe 函数来演示空接口的灵活性。

总之,空接口 interface{} 是一种特殊的接口类型,在 Go 语言中起到了非常重要的作用,它允许我们在不知道具体类型的情况下处理各种值。

结构体

上面JSON转换的时候结构体是这样写的:

代码语言:javascript
复制
type Person struct {
	Name string `json:"name"`
	Age  int    `json:"age"`
}

在 Go 语言中,结构体(struct)中的字段类型后面的 json:"name" 是用于定义字段的 JSON 编码/解码时的特殊标签(tag)。

这种标签的作用是为结构体字段添加额外的元信息,用于在编码和解码 JSON 数据时指定字段的名称、忽略字段等属性。

在给定的示例中,json:"name"json:"age" 是用于指定字段在 JSON 编码/解码过程中对应的名称。

这意味着当使用 Go 的 encoding/json 包编码该结构体实例时,Name 字段会被编码为 JSON 对象的 name 属性,Age 字段会被编码为 JSON 对象的 age 属性。

以下是一个示例说明如何使用结构体标签进行 JSON 编码/解码:

代码语言:javascript
复制
package main

import (
	"encoding/json"
	"fmt"
)

type Person struct {
	Name string `json:"name"`
	Age  int    `json:"age"`
}

func main() {
	p := Person{"Alice", 30}

	// 编码结构体为 JSON
	jsonData, err := json.Marshal(p)
	if err != nil {
		fmt.Println("JSON encode error:", err)
		return
	}

	fmt.Println(string(jsonData)) // 输出: {"name":"Alice","age":30}

	// 解码 JSON 到结构体
	var p2 Person
	err = json.Unmarshal(jsonData, &p2)
	if err != nil {
		fmt.Println("JSON decode error:", err)
		return
	}

	fmt.Println(p2) // 输出: {Alice 30}
}

在上面的示例中,我们定义了一个Person结构体,其中每个字段都有一个类似json:"name"的标签。

使用json.Marshal函数将Person实例编码为 JSON 数据时,编码器会根据这些标签将字段名映射到 JSON 对象中的属性名。

相反,json.Unmarshal函数则依据这些标签将 JSON 数据的属性名映射回结构体的字段。

总之,类型后面的 json:"name" 是结构体字段的标签,用于定义该字段在 JSON 编码/解码过程中的属性。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2024-02-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 查看是否支持泛型
  • 简单的JSON转换
  • 带泛型的JSON转换
  • JSON转换工具类
    • 工具类
      • 测试
      • JSON转换工具类(泛型)
        • 工具类
          • 测试
          • 两者结合
          • 知识点
            • interface{}
              • 结构体
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档