type A struct {
Val string `json:"val"`
Val2 int `json:"val2"`
}
type testA struct {
Val string `json:"val,omitempty"`
Val2 int `json:"val2,omitempty"`
}
func Test(t *testing.T) {
a := A{
Val: "some",
Val2: 0,
}
t.Run("cast", func(t *testing.T) {
ab, _ := json.Marshal(a)
t.Log(string(ab))
ab, _ = json.Marshal(testA(a))
t.Log(string(ab))
})
}
=== RUN Test
=== RUN Test/cust
some_test.go:26: {"val":"some","val2":0}
some_test.go:28: {"val":"some"}
--- PASS: Test (0.00s)
--- PASS: Test/cust (0.00s)
type testAV2 A
func (u testAV2) MarshalJSON() ([]byte, error) {
value := reflect.ValueOf(u)
t := value.Type()
sf := make([]reflect.StructField, 0)
// modify the 'fori' snippet for more complicated cases
for i := 0; i < t.NumField(); i++ {
sf = append(sf, t.Field(i))
tag := t.Field(i).Tag
if !strings.Contains(string(tag), ",omitempty") {
r := regexp.MustCompile(`json:"\s*(.*?)\s*"`)
matches := r.FindAllStringSubmatch(string(tag), -1)
for _, v := range matches {
tagKey := v[1]
sf[i].Tag = reflect.StructTag(fmt.Sprintf(`json:"%s,omitempty"`, tagKey))
}
}
}
newType := reflect.StructOf(sf)
newValue := value.Convert(newType)
return json.Marshal(newValue.Interface())
}
1条答案
按热度按时间monwx1rj1#
最简单的方法是使用与
A
相同的字段创建新类型进行测试,并在测试中使用一个:PLAYGROUND
另一种方法是基于
A
创建新类型,实现新类型的Marshaler,并动态使用reflect包创建具有相同字段和标记的结构体(使用omitempty
):PLAYGROUND