在Go语言开发过程中,经常会遇到需要把数据序列化为JSON格式的场景,其中混合类型JSON数组的序列化是很多开发者容易遇到问题的地方。混合类型JSON数组指的是数组中包含字符串、数字、布尔值、对象、数组等多种不同数据类型的元素,比如[1, "hello", true, {"name": "test"}, [1,2]]这样的结构。

使用原生interface{}类型实现序列化
Go的encoding/json标准库支持将[]interface{}类型序列化为JSON数组,因为interface{}可以接收任意类型的值,正好匹配混合类型数组的需求。我们可以先构造一个[]interface{}切片,往里面添加不同类型的元素,再调用json.Marshal方法完成序列化。
package main
import (
"encoding/json"
"fmt"
)
func main() {
// 构造混合类型数组
mixedArr := []interface{}{
1,
"hello world",
true,
map[string]string{"name": "张三", "age": "20"},
[]int{1, 2, 3},
}
// 执行序列化
data, err := json.Marshal(mixedArr)
if err != nil {
fmt.Println("序列化失败:", err)
return
}
// 输出结果
fmt.Println(string(data))
}
上述代码的输出结果为[1,"hello world",true,{"age":"20","name":"张三"},[1,2,3]],完全符合混合类型JSON数组的预期格式。
自定义类型处理复杂混合场景
如果混合数组中的元素有固定的结构,或者需要自定义序列化逻辑,可以定义自定义类型并实现json.Marshaler接口。比如我们需要序列化一个包含用户信息和状态标识的混合数组,其中用户信息是结构体,状态是布尔值。
package main
import (
"encoding/json"
"fmt"
)
// 定义用户结构体
type User struct {
Name string `json:"name"`
Age int `json:"age"`
}
// 自定义混合数组元素类型
type MixedItem struct {
User *User
IsVip bool
}
// 实现MarshalJSON方法
func (m MixedItem) MarshalJSON() ([]byte, error) {
// 构造临时的混合数组
arr := []interface{}{
m.User,
m.IsVip,
}
return json.Marshal(arr)
}
func main() {
items := []MixedItem{
{User: &User{Name: "李四", Age: 25}, IsVip: true},
{User: &User{Name: "王五", Age: 30}, IsVip: false},
}
data, err := json.Marshal(items)
if err != nil {
fmt.Println("序列化失败:", err)
return
}
fmt.Println(string(data))
}
运行上述代码会输出[{"name":"李四","age":25},true,{"name":"王五","age":30},false],实现了自定义结构的混合类型数组序列化。
注意事项
- 使用
interface{}类型时,数值类型默认会被序列化为float64,如果需要保持整数类型,可以在构造切片时明确使用int等类型,或者在序列化后做类型处理。 - 如果混合数组中包含指针类型,要确保指针不为空,否则序列化时会出现异常结果。
- 自定义序列化逻辑时,要注意避免循环引用,否则会导致序列化陷入死循环。
常见问题解答
序列化后数字变成浮点数怎么办
这是因为interface{}接收数字时默认会推断为float64类型,可以在构造数组时显式使用json.Number类型,示例如下:
package main
import (
"encoding/json"
"fmt"
)
func main() {
mixedArr := []interface{}{
json.Number("123"),
"test",
}
data, _ := json.Marshal(mixedArr)
fmt.Println(string(data))
}
上述代码输出的数字会保持字符串形式的整数,不会变成浮点数。
如何反序列化混合类型JSON数组
反序列化时同样可以使用[]interface{}接收结果,之后再根据元素的实际类型做类型断言处理,示例如下:
package main
import (
"encoding/json"
"fmt"
)
func main() {
jsonStr := `[1, "hello", true]`
var result []interface{}
err := json.Unmarshal([]byte(jsonStr), &result)
if err != nil {
fmt.Println("反序列化失败:", err)
return
}
for _, v := range result {
switch val := v.(type) {
case float64:
fmt.Printf("数字类型: %vn", val)
case string:
fmt.Printf("字符串类型: %vn", val)
case bool:
fmt.Printf("布尔类型: %vn", val)
}
}
}
GoJSON序列化混合类型数组encoding_json修改时间:2026-07-05 00:51:13