Golang中如何序列化与反序列化多种不同的JSON结构体
Golang中如何序列化与反序列化多种不同的JSON结构体 我想将多个不同的结构体存储在JSON文件中,以便读取并执行特定操作。其中一个结构体包含多个字段,例如:
type copyFile struct {
Src string `json:"src"`
Dst string `json:"dst"`
Sudo bool `json:"sudo"`
OverWrite bool `json:"overwrite"`
}
另一个结构体仅包含用户命令,例如:
type userCommand struct {
Cmd string `json:"cmd"`
}
如果我将它们都放入数组并使用json.Marshal处理,会得到类似这样的结果:
[{“cmd”:“echo user command”},{“src”:"/dir/src",“dst”:"/dir/dst",“sudo”:true,“overwrite”:false}]
应该如何对这个结果进行Unmarshal?
目前我已经将copyFile结构体改为:
type copyFile struct {
Cmd string `json:"copy"`
}
然后使用分隔符连接src、dst、sudo和overwrite字段,这样我就可以通过以下方式对整个内容进行Unmarshal:
x, _ := json.Marshal(commandsArray)
var data []map[string]string
err := json.Unmarshall(x,&data)
这种方法有效,我只需要对copyFile的Cmd字段使用strings.Split()即可。但我不知道是否还有其他方法可以保持结构体的完整性。
有人有什么建议吗?我是Go语言的新手,目前还在摸索中。
谢谢
更多关于Golang中如何序列化与反序列化多种不同的JSON结构体的实战教程也可以访问 https://www.itying.com/category-94-b0.html
可以使用一个非常简单的结构体
typedef cmd struct {
Cmd string `json:"cmd"`
Args []string `json:"args"`
}
更多关于Golang中如何序列化与反序列化多种不同的JSON结构体的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
即使我将当前的 copyFile 结构保留为单个 Cmd 字符串,就像 userCommand 一样,我也会将它们分开处理。部分原因是我可以通过 JSON 文件中的映射键来"标记"要执行的操作。例如,如果 copyFile 是一个带有分隔符的单个字符串(本例中使用"%"),我最终会得到:
[{"copy":"/dir/src%/dir/dst%true%false"},{"cmd":"echo user command"}]
在解组数据之后,我可以根据键来判断要执行什么操作。如果所有对象都用相同的结构表示,那么(至少据我所知)就没有办法对它们进行不同的标记。
谢谢。
可以使用Go的json.RawMessage来处理多种不同结构的JSON数组。这种方法能够保持每个结构体的完整性,不需要修改原始结构体定义。
首先定义原始结构体:
type copyFile struct {
Src string `json:"src"`
Dst string `json:"dst"`
Sudo bool `json:"sudo"`
OverWrite bool `json:"overwrite"`
}
type userCommand struct {
Cmd string `json:"cmd"`
}
然后创建包装器类型来处理混合JSON数组:
type CommandWrapper struct {
Type string `json:"type"` // 用于标识命令类型
Data json.RawMessage `json:"data"` // 存储原始JSON数据
}
序列化示例:
func serializeCommands(commands []interface{}) ([]byte, error) {
var wrappers []CommandWrapper
for _, cmd := range commands {
var wrapper CommandWrapper
var rawData []byte
var err error
switch v := cmd.(type) {
case copyFile:
wrapper.Type = "copyFile"
rawData, err = json.Marshal(v)
case userCommand:
wrapper.Type = "userCommand"
rawData, err = json.Marshal(v)
default:
return nil, fmt.Errorf("unknown command type")
}
if err != nil {
return nil, err
}
wrapper.Data = rawData
wrappers = append(wrappers, wrapper)
}
return json.Marshal(wrappers)
}
反序列化示例:
func deserializeCommands(data []byte) ([]interface{}, error) {
var wrappers []CommandWrapper
err := json.Unmarshal(data, &wrappers)
if err != nil {
return nil, err
}
var commands []interface{}
for _, wrapper := range wrappers {
switch wrapper.Type {
case "copyFile":
var cf copyFile
err := json.Unmarshal(wrapper.Data, &cf)
if err != nil {
return nil, err
}
commands = append(commands, cf)
case "userCommand":
var uc userCommand
err := json.Unmarshal(wrapper.Data, &uc)
if err != nil {
return nil, err
}
commands = append(commands, uc)
default:
return nil, fmt.Errorf("unknown command type: %s", wrapper.Type)
}
}
return commands, nil
}
使用示例:
// 创建混合命令数组
commands := []interface{}{
userCommand{Cmd: "echo user command"},
copyFile{
Src: "/dir/src",
Dst: "/dir/dst",
Sudo: true,
OverWrite: false,
},
}
// 序列化
data, err := serializeCommands(commands)
if err != nil {
log.Fatal(err)
}
// 反序列化
decodedCommands, err := deserializeCommands(data)
if err != nil {
log.Fatal(err)
}
// 使用命令
for _, cmd := range decodedCommands {
switch v := cmd.(type) {
case userCommand:
fmt.Printf("User command: %s\n", v.Cmd)
case copyFile:
fmt.Printf("Copy file from %s to %s\n", v.Src, v.Dst)
}
}
这种方法保持了每个结构体的完整性,不需要对字段进行字符串分割操作。

