fatih/structtag

Question: Modify struct tag and then re-marshal json

brondum opened this issue · 2 comments

Hi.
Is it possible to re-marshal the response after mutating the structtags?

eg.

package main

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

	"github.com/fatih/structtag"
)

func main() {
	type Payload struct {
		Someting string `json:"something"`
	}

	// get field tag
	tag := reflect.TypeOf(Payload{}).Field(0).Tag

	// ... and start using structtag by parsing the tag
	tags, err := structtag.Parse(string(tag))
	if err != nil {
		fmt.Printf("error parsing tags: %v", err)
	}
	fmt.Println(tags)

	err = tags.Set(&structtag.Tag{
		Key:     "json",
		Name:    "bar",
		Options: []string{},
	})
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(tags)

	payload := Payload{Someting: "woop"}

	resp, err := json.Marshal(payload)
	if err != nil {
		fmt.Printf("error marshaling payload: %v", err)
	}

	fmt.Printf("%s\n\n", resp)

}

Current response:

json:"something"
json:"bar"
{"something":"woop"}

expected result:

json:"something"
json:"bar"
{"bar":"woop"}

Thank you in advance

fatih commented

This is not part of the library but you can use the reflect package to achieve it. Here is an example based on your comment: https://play.golang.org/p/YsaqhVHTHJJ

package main

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

	"github.com/fatih/structtag"
)

func main() {
	type Payload struct {
		Someting string `json:"someting"`
	}

	p := Payload{}

	// get field tag
	pt := reflect.TypeOf(p)
	tag := pt.Field(0).Tag

	// ... and start using structtag by parsing the tag
	tags, err := structtag.Parse(string(tag))
	if err != nil {
		fmt.Printf("error parsing tags: %v", err)
	}
	fmt.Println(tags)

	err = tags.Set(&structtag.Tag{
		Key:     "json",
		Name:    "bar",
		Options: []string{},
	})
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(tags)

	st := []reflect.StructField{}
	for i := 0; i < pt.NumField(); i++ {
		st = append(st, pt.Field(i))
	}

	// replace with our modified tag
	st[0].Tag = reflect.StructTag(tags.String())

	p2 := reflect.StructOf(st)
	v := reflect.ValueOf(p)
	v2 := v.Convert(p2)

	resp, err := json.Marshal(v2.Interface())
	if err != nil {
		fmt.Printf("error marshaling payload: %v", err)
	}

	fmt.Printf("%s\n\n", resp)
}

Closing this as I don't think there is much I can do on my end. Thank you

@fatih Thank you for the answer, and the example with reflect :)