golang MarshalJson的实现

 更新时间:2025年03月04日 09:17:54   作者:get200  
本文主要介绍了golang MarshalJson的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

在 Go 语言中,MarshalJSON 是一个接口方法,允许自定义类型在进行 JSON 编码时提供自定义的序列化逻辑。通过实现 MarshalJSON 方法,你可以控制结构体或其他类型在转换为 JSON 时的表现。

基本用法

当你想要自定义某个类型的 JSON 表现时,可以实现 json.Marshaler 接口,该接口只包含一个方法 MarshalJSON。实现该方法后,使用 json.Marshal 函数时会自动调用你定义的 MarshalJSON 方法。

示例

以下是一个示例,展示如何自定义结构体的 JSON 序列化:

package main

import (
    "encoding/json"
    "fmt"
)

// 定义一个结构体
type User struct {
    Name  string
    Age   int
    Email string
}

// 为 User 实现 MarshalJSON 方法
func (u User) MarshalJSON() ([]byte, error) {
    // 自定义 JSON 输出格式
    return json.Marshal(struct {
        FullName string `json:"name"`
        Age      int    `json:"age"`
        Email    string `json:"email_address"`
    }{
        FullName: u.Name,
        Age:      u.Age,
        Email:    u.Email,
    })
}

func main() {
    user := User{Name: "Alice", Age: 30, Email: "alice@example.com"}

    // Marshal 用户对象为 JSON
    jsonData, err := json.Marshal(user)
    if err != nil {
        fmt.Println("Error marshaling to JSON:", err)
        return
    }

    fmt.Println(string(jsonData)) // 输出: {"name":"Alice","age":30,"email_address":"alice@example.com"}
}

解释

  • 定义结构体:我们定义了一个 User 结构体,包含 NameAge 和 Email 字段。
  • 实现 MarshalJSON 方法:我们为 User 结构体实现了 MarshalJSON 方法。在这个方法中,我们自定义了 JSON 输出格式。
  • 自定义输出:在 MarshalJSON 方法中,我们使用匿名结构体来定义最终的 JSON 格式。
  • 使用 json.Marshal:在 main 函数中,我们创建了一个 User 实例,并使用 json.Marshal 将其转换为 JSON 字符串。

注意事项

  • 错误处理MarshalJSON 方法应返回 error,以便在序列化过程中可以处理潜在的错误。
  • 递归调用:在 MarshalJSON 方法中,如果调用 json.Marshal,需要确保所处理的结构体不会递归调用自身的 MarshalJSON 方法。

Marshal函数将会递归遍历整个对象,依次按成员类型对这个对象进行编码。

类型转换规则如下:

  • bool类型:转换为JSON的Boolean
  • 整数、浮点数等数值类型: 转换为JSON的Number
  • string类型: 转换为JSON的字符串(带""引号)
  • struct类型:转换为JSON的Object,再根据各个成员的类型递归打包
  • 数组或切片类型: 转换为JSON的Array
  • []byte类型: 会先进行base64编码然后转换为JSON字符串
  • map类型:转换为JSON的Object,key必须是string
  • interface{}类型: 按照内部的实际类型进行转换
  • nil类型: 转为JSON的null
  • channel,func等类型: 会返回UnsupportedTypeError

从golang到json:

golangjson
boolBoolean
int、float等数字Number
stringString
[]byte(base64编码)String
structObject,再递归打包
array/sliceArray
mapObject
interface{}按实际类型转换
nilnull
channel,funcUnsupportedTypeError

从json到golang:

jsongolang
Booleanbool
Numberfloat64
Stringstring
Array[]interface{}
Objectmap[string]interface{}
nullnil

避坑

json.marshal使用不当,会存在base64编码问题问题出现在:[]byte 在json.marshal时会进行base64 encoding处理

解决办法:使用json.RawMessagejson.RawMessage其实就是[]byte类型的重定义。可以进行强制类型转换。

现在有这么一种场景,结构体中的其中一个字段的格式是未知的:

type Command struct {  
    ID   int  
    Cmd  string  
    Args *json.RawMessage  
}  

使用json.RawMessage的话,Args字段在Unmarshal时不会被解析,直接将字节数据赋值给Args。我们可以能先解包第一层的JSON数据,然后根据Cmd的值,再确定Args的具体类型进行第二次Unmarshal。

注意:一定要使用指针类型*json.RawMessage,否则在Args会被认为是[]byte类型,在打包时会被打包成base64编码的字符串。

使用interface{}, interface{}类型在Unmarshal时,会自动将JSON转换为对应的数据类型:

JSON的boolean: 转换为bool
JSON的数值: 转换为float64
JSON的字符串: 转换为string
JSON的Array: 转换为[]interface{}
JSON的Object: 转换为map[string]interface{}
JSON的null: 转换为nil

需要注意的有两个:

  • 一是所有的JSON数值自动转换为float64类型,使用时需要再手动转换为需要的int,int64等类型。
  • 二是JSON的object自动转换为map[string]interface{}类型,访问时直接用JSON Object的字段名作为key进行访问。在不知道JSON数据的格式时,可以使用interface{}。

自定义类型:如果希望自己定义对象的打包解包方式,可以实现以下的接口:

type Marshaler interface {  
    MarshalJSON() ([]byte, error)  
}  
type Unmarshaler interface {  
    UnmarshalJSON([]byte) error  
}  

实现该接口的对象需要将自己的数据打包和解包。如果实现了该接口,json在打包解包时则会调用自定义的方法,不再对该对象进行其他处理。

总结

通过实现 MarshalJSON 方法,可以为 Go 的自定义类型提供灵活的 JSON 序列化控制。这使得在与 JSON 数据交互时,可以更好地控制数据的结构和格式。

到此这篇关于golang MarshalJson的实现的文章就介绍到这了,更多相关golang MarshalJson内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • go的strings用法小结

    go的strings用法小结

    strings 是 Go 语言标准库中提供的一个包,用于处理字符串相关的操作,本文主要介绍了go的strings用法小结,具有一定的参考价值,感兴趣的可以了解一下
    2023-08-08
  • golang 占位符和fmt常见输出介绍

    golang 占位符和fmt常见输出介绍

    这篇文章主要介绍了golang 占位符和fmt常见输出介绍,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • Go泛型之泛型约束示例详解

    Go泛型之泛型约束示例详解

    这篇文章主要给大家介绍了关于Go泛型之泛型约束的相关资料,泛型是静态语言中的一种编程方式,这种编程方式可以让算法不再依赖于某个具体的数据类型,而是通过将数据类型进行参数化,以达到算法可复用的目的,需要的朋友可以参考下
    2023-12-12
  • Go的gin参数校验中的validator库详解

    Go的gin参数校验中的validator库详解

    这篇文章主要介绍了Go的gin参数校验之validator库,使用 validator 以后,只需要在定义结构体时使用 binding 或 validate tag标识相关校验规则,就可以进行参数校验了,而不用自己单独去写常见的校验规则,需要的朋友可以参考下
    2023-08-08
  • Go tablewriter库提升命令行输出专业度实例详解

    Go tablewriter库提升命令行输出专业度实例详解

    命令行工具大家都用过,如果是运维人员可能会编写命令行工具来完成各种任务,命令行输出的美观和易读性往往容易被忽视,很烂的输出会让人感觉不专业,本文将介绍Go语言中牛逼的实战工具tablewriter库,使你在命令行输出中展现出专业的一面
    2023-11-11
  • golang gopm get -g -v 无法获取第三方库的解决方案

    golang gopm get -g -v 无法获取第三方库的解决方案

    这篇文章主要介绍了golang gopm get -g -v 无法获取第三方库的解决方案,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-05-05
  • 轻松入门:使用Golang开发跨平台GUI应用

    轻松入门:使用Golang开发跨平台GUI应用

    Golang是一种强大的编程语言,它的并发性和高性能使其成为开发GUI桌面应用的理想选择,Golang提供了丰富的标准库和第三方库,可以轻松地创建跨平台的GUI应用程序,通过使用Golang的GUI库,开发人员可以快速构建具有丰富用户界面和交互功能的应用程序,需要的朋友可以参考下
    2023-10-10
  • golang简单获取上传文件大小的实现代码

    golang简单获取上传文件大小的实现代码

    这篇文章主要介绍了golang简单获取上传文件大小的方法,涉及Go语言文件传输及文件属性操作的相关技巧,需要的朋友可以参考下
    2016-07-07
  • 使用golang引入外部包的三种方式:go get, go module, vendor目录

    使用golang引入外部包的三种方式:go get, go module, ve

    这篇文章主要介绍了使用golang引入外部包的三种方式:go get, go module, vendor目录,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01
  • Golang中Json的序列化和反序列化的使用

    Golang中Json的序列化和反序列化的使用

    本文主要介绍了Golang中Json的序列化和反序列化的使用,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-04-04

最新评论