我们获得一些JSON输入,解组,执行一些工作,然后编组并在其他地方发货。我们得到的JSON可能有一个名为“user”的字段。当我们编组回JSON时,我们需要将该字段“user”更改为“username”。我们可以通过创建一个包含所有相同字段但不同JSON标记的新结构来实现这一点,但这看起来有点麻烦。我以为定制的编组人员会在这里工作,但我有点卡住了。请考虑以下代码。
package main
import (
"encoding/json"
"fmt"
)
type StructA struct {
Username string `json:"user"`
Process string `json:"process"`
}
func main() {
var test1 StructA
err := json.Unmarshal([]byte(`{"user": "user123", "process": "something"}`), &test1)
if err != nil {
fmt.Println(err)
}
// do some work with test1
jsonByte, err := json.Marshal(&test1)
if err != nil {
fmt.Println(err)
}
fmt.Println(string(jsonByte))
}
func (u *StructA) MarshalJSON() ([]byte, error) {
type Alias StructA
return json.Marshal(&struct {
Username string `json:"username"`
*Alias
}{
Username: u.Username,
Alias: (*Alias)(u),
})
}
https://play.golang.org/p/_w0rlQrcgrW
理想情况下,这将允许我将该字段上的JSON标记从“user”更改为“username”。但是,我同时获得“用户名”和“用户”。
{"username":"user123","user":"user123","process":"something"}
我当然可以创建一个全新的结构,用我想要的标签镜像StructA,但我不必复制每个字段,并担心保持这两个结构同步。这不是世界末日,但它似乎不是一个好方法。
要清楚,我正在寻找的最终结果如下:
{"username":"user123","process":"something"}
我确信我在这里遗漏了一些微不足道的事情,但这是一个漫长的一周,任何帮助都会受到赞赏。谢谢!
答案 0 :(得分:1)
一个选项可能是使一个结构具有不变的值,而不是两个包含该结构且仅具有变化值的替代结构。然后你用一个用于解组,第二个用于编组。
type StructA struct {
Process string `json:"process"`
...
}
type WithUser struct {
StructA
Username `json:"user"`
}
type WithUsername struct {
StructA
Username `json:"username"`
}
这需要多个结构但每个结构都没有重复,并且在您所包含的内容中可以非常灵活,而不是硬编码您想要更改为自定义编组功能的内容。
答案 1 :(得分:0)
使用reflect来创建struct并更改它的标签
package main
import (
"encoding/json"
"fmt"
"reflect"
)
type StructA struct {
Username string `json:"user"`
Process string `json:"process"`
}
func main() {
var test1 StructA
err := json.Unmarshal([]byte(`{"user": "user123", "process": "something"}`), &test1)
if err != nil {
fmt.Println(err)
}
// do some work with test1
jsonByte, err := json.Marshal(&test1)
if err != nil {
fmt.Println(err)
}
fmt.Println(string(jsonByte))
}
func (u *StructA) MarshalJSON() ([]byte, error) {
// get old struct fields
uType := reflect.TypeOf(u).Elem()
userNameField, _ := uType.FieldByName("Username")
// set username field tag
userNameField.Tag = `json:"username"`
processField, _ := uType.FieldByName("Process")
newType := reflect.StructOf([]reflect.StructField{userNameField, processField})
// set new value field
oldValue := reflect.ValueOf(u).Elem()
newtValue := reflect.New(newType).Elem()
for i := 0; i < oldValue.NumField(); i++ {
newtValue.Field(i).Set(oldValue.Field(i))
}
return json.Marshal(newtValue.Interface())
}