使用自定义MarshalJSON更改结构中的JSON标记

使用自定义MarshalJSON更改结构中的JSON标记,json,go,Json,Go,我们得到一些JSON输入,解组,执行一些工作,然后编组并发送到其他地方。我们得到的JSON可能有一个名为“user”的字段。当我们封送回JSON时,我们需要将字段“user”更改为“username”。我们可以通过创建一个包含所有相同字段但不同JSON标记的新结构来实现这一点,但这似乎有点麻烦。我原以为一个定制的警察会在这里工作,但我有点卡住了。考虑下面的代码。 package main import ( "encoding/json" "fmt" ) type Struct

我们得到一些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),
    })
}

理想情况下,这将允许我将该字段上的JSON标记从“user”更改为“username”。但是,我同时获得“用户名”和“用户”

我当然可以创建一个全新的结构,用我想要的标记来镜像StructA,但我不必复制每个字段,也不必担心这两个结构保持同步。这不是世界末日,但这似乎不是一个好办法

明确地说,我期待的最终结果如下:

{"username":"user123","process":"something"}

我肯定我错过了一些琐碎的事情,但这是一个漫长的一周,任何帮助都将不胜感激。谢谢

一个选项可以是有一个具有非更改值的结构和两个以上的替代结构,这两个结构都包含该结构并且只有更改值。然后使用一个用于解组,第二个用于封送

type StructA struct {
    Process  string `json:"process"`
    ...
}

type WithUser struct {
    StructA
    Username `json:"user"`
}

type WithUsername struct {
    StructA
    Username `json:"username"`
}

这将需要多个结构,但每个结构中没有重复,并且在所包含的内容中可以非常灵活,而不是硬编码要更改为自定义封送处理函数的内容。

使用反射创建结构并更改其标记

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())
}
主程序包
进口(
“编码/json”
“fmt”
“反映”
)
类型StructA struct{
用户名字符串`json:“用户”`
进程字符串`json:“进程”`
}
func main(){
var test1 StructA
err:=json.Unmarshal([]字节(`{“user”:“user123”,“process”:“something”}`),和test1)
如果错误!=零{
fmt.Println(错误)
}
//使用test1做一些工作
jsonByte,err:=json.Marshal(&test1)
如果错误!=零{
fmt.Println(错误)
}
fmt.Println(字符串(jsonByte))
}
func(u*StructA)MarshalJSON()([]字节,错误){
//获取旧结构字段
uType:=reflect.TypeOf(u).Elem()
userNameField,\:=uType.FieldByName(“用户名”)
//设置用户名字段标记
标记=`json:“用户名”`
processField,U4:=uType.FieldByName(“进程”)
newType:=reflect.StructOf([]reflect.StructField{userNameField,processField})
//设置新值字段
oldValue:=reflect.ValueOf(u).Elem()
newtValue:=reflect.New(newType.Elem())
对于i:=0;i
您得到的结果是,您在创建要封送的新结构时嵌入了该结构。您已经嵌入了整个
StructA
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())
}