如何在结构字段上不使用 omitempty 进行 json 编组

问题描述 投票:0回答:1

我有一个生成类型

A

我想要

json.Marshal
类型并在测试时忽略任何空字段。

生成的类型对于任何结构字段都没有

json:",omitempty"
,我也不想出于应用程序本身的目的。

在不提供空字段的情况下整理我的类型的最佳方法是什么?

干杯!

json go marshalling
1个回答
1
投票

最简单的方法是使用与

A
相同的字段创建新类型进行测试,并在测试中使用一个:

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)

游乐场

另一种方法是基于

A
创建新类型,为新类型实现 Marshaler 并创建具有相同字段和标签(使用
omitempty
)的结构,动态使用 reflect 包:

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

游乐场

© www.soinside.com 2019 - 2024. All rights reserved.