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 用户对象为 JS编程客栈ON 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
结构体,包含Name
、Age
和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,再根据各个成员的类型递python归打包
- 数组或切片类型: 转换为JSON的Array
- []byte类型: 会先进行base64编码然后转换为JSON字符串
- map类型:转换为JSON的Object,key必须是string
- interface{}类型: 按照内部的实际类型进行转换
- nil类型: 转为JSON的null
- channel,func等类型: 会返回UnsupportedTypeError
从golang到json:
golang | json |
---|---|
bool | Boolean |
int、float等数字 | Number |
string | String |
[]byte(base64编码) | String |
struct | Object,再递归打包 |
array/slice | Array |
map | Object |
interface{} | 按实际类型转换 |
nil | null |
channel,func | UnsupportedTypeError |
从json到golang:
json | golang |
---|---|
Boolean | bool |
Number | float64 |
String | string |
Array | []interface{} |
Object | map[string]interface{} |
null | nil |
避坑
json.marshal使用不当,会存在base64编码问题问题出现在php:[]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的数值: 转换为float64JSON的字符串: 转换为stringJSON的Array: 转换为[]interface{}JSON的Object: 转换为map[string]interface{}JSON的null: 转换为nil
需要注意的有两个:
- 一是所有的JSON数值自动转换为float64类型,使用时需要再手动转换为需要的int,int64等类型。
- 二是JSON的object自动转换为
map[string]interface{}
类型,访问时直接用JSON Object的字段名作为key进行访问。在不知道JSON数据的格式时,可以使用interface{}。
自定义类型:如果希望自己定义对象的打包解包方式,可以实javascript现以下的接口:
type Marshaler interface { MarshalJSON() ([]byte, error) } type Unmarshaler interface { UnmarshalJSON([]byte) error }
实现该接口的对象需要将自己的数据打包和解包。如果实现了该接口,json在打包解包时则会调用自定义的方法,不再对该对象进行其他处理。
总结
通过实现 MarshalJSON
方法,可以为 Go 的自定义类型提供灵活的 编程JSON 序列化控制。这使得在与 JSON 数据交互时,可以更好地控制数据的结构和格式。
到此这篇关于golang MarshalJson的实现的文章就介绍到这了,更多相关golang MarshalJson内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!
精彩评论