一尘不染

如何动态更改结构的json标签?

go

我有以下几点:

package main

import (
    "encoding/json"
    "fmt"
    "os"
    "reflect"
)

type User struct {
    ID   int64  `json:"id"`
    Name string `json:"first"` // want to change this to `json:"name"`
    tag  string `json:"-"`
    Another
}

type Another struct {
    Address string `json:"address"`
}

func (u *User) MarshalJSON() ([]byte, error) {
    value := reflect.ValueOf(*u)
    for i := 0; i < value.NumField(); i++ {
        tag := value.Type().Field(i).Tag.Get("json")
        field := value.Field(i)
        fmt.Println(tag, field)
    }
    return json.Marshal(u)
}

func main() {
        anoth := Another{"123 Jennings Street"}
    _ = json.NewEncoder(os.Stdout).Encode(
        &User{1, "Ken Jennings", "name",
             anoth},
    )
}

我正在尝试对结构进行json编码,但是在我需要更改json键之前,例如,最终的json应该如下所示:

{"id": 1, "name": "Ken Jennings", "address": "123 Jennings Street"}

我注意到value.Type()。Field(i).Tag.Get(“ json”)的方法,但是没有设置方法。为什么?以及如何获取所需的json输出。

另外,如何遍历所有字段,包括嵌入式结构Another?

https://play.golang.org/p/Qi8Jq_4W0t


阅读 194

收藏
2020-07-02

共1个答案

一尘不染

这很麻烦,但是如果您可以将该结构包装在另一个结构中,并使用新的结构进行编码,则可以:

  1. 编码原始结构,
  2. 解码为interface{}以获得地图
  3. 更换地图钥匙
  4. 然后对地图进行编码并返回

从而:

type MyUser struct {
    U User
}

func (u MyUser) MarshalJSON() ([]byte, error) {
    // encode the original
    m, _ := json.Marshal(u.U)

    // decode it back to get a map
    var a interface{}
    json.Unmarshal(m, &a)
    b := a.(map[string]interface{})

    // Replace the map key
    b["name"] = b["first"]
    delete(b, "first")

    // Return encoding of the map
    return json.Marshal(b)
}

在操场上:https :
//play.golang.org/p/TabSga4i17

2020-07-02