Can I skip a json tag while Marshalling a struct in Golang?

huangapple go评论97阅读模式
英文:

Can I skip a json tag while Marshalling a struct in Golang?

问题

我有一个场景,我想在Golang中编组结构体时跳过一个JSON标签。这可能吗?如果可以,我该如何实现?

例如,我得到了这个JSON:
{"Employee":{"Interface":{"Name":"xyz", "Address":"abc"}}}

但我希望JSON是这样的:
{"Employee":{"Name":"xyz", "Address":"abc"}}

英文:

I have a scenario where I would like to skip a json tag while marshalling a struct in Golang. Is that possible? If so how can I achieve this?

For example I am getting this json:
{"Employee":{"Interface":{"Name":"xyz", "Address":"abc"}}}

But I want the json to be:
{"Employee":{"Name":"xyz", "Address":"abc"}}

答案1

得分: 1

你可以使用匿名结构体

type Employee struct {
	Interface struct {
		Name    string
		Address string
	}
}

func main() {
	a := Employee{
		Interface: struct {
			Name    string
			Address string
		}{
			Name:    "xyz",
			Address: "abc",
		},
	}
	b := struct {
		Employee struct {
			Name    string
			Address string
		}
	}{
		Employee: a.Interface,
	}
	jsonResult, _ := json.Marshal(b)
	fmt.Println(string(jsonResult)) // {"Employee":{"Name":"xyz","Address":"abc"}}
}
英文:

You can use anonymous structures

type Employee struct {
	Interface Interface
}
type Interface struct {
	Name string
	Address string
}
func main() {
    a := Employee{Interface: Interface{Name: "xyz", Address: "abc"}}
	b := struct {
		Employee Interface
	}{
		Employee: a.Interface,
	}
	jsonResult, _ := json.Marshal(b)
	fmt.Println(string(jsonResult)) // {"Employee":{"Name":"xyz","Address":"abc"}}
}

答案2

得分: 1

如果Interface字段的类型不是一个实际的接口类型,而是一个结构体类型,那么你可以嵌入该字段,这将使嵌入的结构体字段成为Employee的一部分,并将其编组为JSON以获得所需的输出。

type Employee struct {
	Interface // 嵌入字段
}

type Interface struct {
	Name    string
	Address string
}

func main() {
	type Output struct{ Employee Employee }

	e := Employee{Interface: Interface{Name: "xyz", Address: "abc"}}
	out, err := json.Marshal(Output{e})
	if err != nil {
		panic(err)
	}
	fmt.Println(string(out))
}

如果Interface字段的类型是一个实际的接口类型,那么嵌入将无法帮助,相反,你可以让Employee类型实现json.Marshaler接口,并自定义生成的JSON。

例如,你可以这样做:

type Employee struct {
	Interface Interface `json:"-"`
}

func (e Employee) MarshalJSON() ([]byte, error) {
    type E Employee
	obj1, err := json.Marshal(E(e))
	if err != nil {
		return nil, err
	}

	obj2, err := json.Marshal(e.Interface)
	if err != nil {
		return nil, err
	}

    // 通过从obj1中删除'}'和从obj2中删除'{',然后将obj2附加到obj1来连接两个对象
    //
    // 注意:如果Interface字段为nil,或者它包含的类型不是结构体、映射或指向这些类型的指针,则会生成无效的JSON,并且编组将失败并报错。
    // 如果你的程序中可能出现这些情况,你应该在这里添加一些逻辑来处理它们。
	return append(obj1[:len(obj1)-1], obj2[1:]...), nil
}
英文:

If the Interface field's type is not an actual interface but a struct type then you could embed that field, this will promote the embedded struct's fields to Employee and marshaling that into JSON will get you the output you want.

type Employee struct {
	Interface // embedded field
}

type Interface struct {
	Name    string
	Address string
}

func main() {
	type Output struct{ Employee Employee }

	e := Employee{Interface: Interface{Name: "xyz", Address: "abc"}}
	out, err := json.Marshal(Output{e})
	if err != nil {
		panic(err)
	}
	fmt.Println(string(out))
}

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


If the Interface field's type is an actual interface type then embedding won't help, instead you could have the Employee type implement the json.Marshaler interface and customize the resulting JSON.

For example you could do the following:

type Employee struct {
	Interface Interface `json:"-"`
}

func (e Employee) MarshalJSON() ([]byte, error) {
    type E Employee
	obj1, err := json.Marshal(E(e))
	if err != nil {
		return nil, err
	}

	obj2, err := json.Marshal(e.Interface)
	if err != nil {
		return nil, err
	}

    // join the two objects by dropping '}' from obj1 and
    // dropping '{' from obj2 and then appending obj2 to obj1
    //
    // NOTE: if the Interface field was nil, or it contained a type
    // other than a struct or a map or a pointer to those, then this
    // will produce invalid JSON and marshal will fail with an error.
    // If you expect those cases to occur in your program you should
    // add some logic here to handle them.
	return append(obj1[:len(obj1)-1], obj2[1:]...), nil
}

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

huangapple
  • 本文由 发表于 2021年11月12日 14:01:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/69938563.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定