How to dynamically change a struct json tag?

I have the following:

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},
    )
}

I am trying to json encode the structure, but before I need to change the json key ... for example, the final json should look like this:

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

I noticed the value.Type () method. Field (i) .Tag.Get ("json"), however there is no setter method. What for? and how do I get the desired json output.

Also, how to iterate over all fields, including the inline structure? Still?

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

+4
source share
2 answers

This is kludgy, but if you can wrap the structure in another and use the new one for encoding, you can:

  • Encode the original structure,
  • Decrypt it interface{}to get a card.
  • Replace card key

:

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

+1

Go 1.8 . :

func main() {
    anoth := Another{"123 Jennings Street"}

    _ = json.NewEncoder(os.Stdout).Encode(
        &User{1, "Ken Jennings", "name",
            anoth},
    )
}

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) {
    type alias struct {
        ID   int64  `json:"id"`
        Name string `json:"name"`
        tag  string `json:"-"`
        Another
    }
    var a alias = alias(*u)
    return json.Marshal(&a)
}

:

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

, Go 1.8 , . , alias , User, .

+4

Source: https://habr.com/ru/post/1671208/


All Articles