Golang Go语言中如何自定义外部类型的JSON序列化方式?

发布于 1周前 作者 nodeper 最后一次编辑是 5天前 来自 Go语言

我要 json 序列化一个外部类型的变量,把所有 int 类型变量都序列化成"010101"这种表示。

类似 Java 里的 Gson ,想把自定义的 int 序列化逻辑注册进去。

这要怎么做到?


不懂就问:Golang Go语言中如何自定义外部类型的JSON序列化方式?
26 回复

更多关于Golang Go语言中如何自定义外部类型的JSON序列化方式?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


自定义类型,实现 MarshalJSON 方法

type MyInt int

func (v MyInt) MarshalJSON() ([]byte, error) {

return big.NewInt(int64(int(v) + 1)).Bytes(), nil
}

func main() {
m := MyInt(1)
json.Marshal(m)
}

#2 代码有点问题,但流程是对的

return big.NewInt(int64(int(v) + 1)).Bytes(), nil




外部类型里的变量是 int ,不是自定义类型。

这样的话,我还需要对这个外部变量再创建一个自定义类型,然后把 int 字段替换成 MyInt 。

如果这个外部变量里面又嵌套了其他外部类型,那我都要对他们每个都创建一个自定义类型。这样写太反人类了。。。

只修改最外层即可

如 type Person struct {name string, age int},只需要实现 Person 的 MarshalJSON ,然后拼接



有点不大明白。这个 Person 是外部类型,我怎么能实现它的 MarshalJSON ?



func (p *Person) MarshalJSON() ([]byte, error) {}



还是有点搞不明白。

这个 Person 是我所引用的库里的类型。可以给这种外部类型实现新的方法?

那就不能了

土办法,引用第三方库的 struct ,你改变不了。那就在你的代码定义一个相同字段的 struct ,然后实现 MarshalJSON()方法

多了一步遍历转换的过程,看 OP 能不能接受

随便找段 json 复制进去就能生成对应的 struct 类型了,这个工具我写 go 时经常用。
https://mholt.github.io/json-to-go/

在 golang 里面应该不行, 大道至简, 别琢磨巧妙的方法了.

大道至简的要义就是, 啰嗦就啰嗦, 多点代码也没啥, 省脑子.

可以用 github.com/json-iterator/go 的扩展功能给 int 类型注册一个自定义编码

原生做法感觉只能定义一个一样的 struct 然后自定义字段序列化方式,加一步数据的转换

go 里方法定义得和类型定义在一个包里,这样应该搞不定。




这个库貌似可以实现,但实在有点抗拒为了这功能又引入一个新东西。。。多谢老歌






这也是我想到的:先写一些数据作为中间层,把全部的外部类型都继承一遍。。。。

没想到只能这么写。。。对 go 这语言改观了。。

多谢大家

代码很贴心,投币感谢了!

你想要的是类似 swift 的 extension ,任意地方可以扩展一个类的方法。这样的坏处是 implicitity ,你用了一堆库,某个库把另一个库的 MashalJSON 给改了,你得到的结果就是一头雾水,明明自己没改呀。


这个看设计,因为 go 里面的序列化器都是全局的,所以改一个地方就会影响好多个地方。

像 java 的 Gson 就不会,用的时候新建一个 instance 然后注册进逻辑就可以,只有使用它的地方才带这个逻辑。

你说的自定义 json 序列化方式是加 tag 吗?

你可以自定义一个自己的完全一样的 struct
type MyPerson struct {
name string 我的自定义 tag
age int
home Home
}

然后把 p 强制类型转换后再序列化

json.Marshal(MyPerson§)

不是。我说的是把’{“name”: “Alice”, “age”: 10, “home”: {“district”: “XX”, “number”: 1}}’,变成’{“name”: “Alice”, “age”: “1010”, “home”: {“district”: “XX”, “number”: “01”}}'这样,就是把里面所有的 int 数值类型全部换一个序列化方式。

是需要引入中间变量

在Go语言中,自定义外部类型的JSON序列化方式通常通过实现json.Marshalerjson.Unmarshaler接口来完成。这两个接口分别定义了如何将自定义类型序列化为JSON字符串,以及如何将JSON字符串反序列化为自定义类型。

以下是一个简单的示例,展示如何为自定义类型实现这两个接口:

package main

import (
	"encoding/json"
	"fmt"
)

type CustomType struct {
	Field1 int
	Field2 string
}

func (c CustomType) MarshalJSON() ([]byte, error) {
	type Alias CustomType // 避免递归调用
	return json.Marshal(&struct {
		CustomField string `json:"custom_field"`
		*Alias
	}{
		CustomField: fmt.Sprintf("%d-%s", c.Field1, c.Field2),
		Alias:       (*Alias)(&c),
	})
}

func (c *CustomType) UnmarshalJSON(data []byte) error {
	type Alias CustomType
	aux := &struct {
		CustomField string `json:"custom_field"`
		*Alias
	}{
		Alias: (*Alias)(c),
	}
	if err := json.Unmarshal(data, &aux); err != nil {
		return err
	}
	// 解析CustomField并设置到Field1和Field2(这里需要自定义逻辑)
	// 例如:简单的字符串分割(实际场景中可能需要更复杂的解析)
	parts := aux.CustomField[:len(aux.CustomField)-1] // 假设去掉最后一个字符'-'
	fmt.Sscanf(parts, "%d-%s", &c.Field1, &c.Field2)
	return nil
}

func main() {}

通过这种方式,你可以完全控制自定义类型在JSON中的表示形式。

回到顶部