空的或者不需要的结构字段

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

Empty or not required struct fields

问题

我有两个结构体,表示将插入到MongoDB数据库中的模型。其中一个结构体(Investment)的一个字段是另一个结构体(Group)。

type Group struct {
    Base
    Name string `json:"name" bson:"name"`
}

type Investment struct {
    Base
    Symbol string `json:"symbol" bson:"symbol" binding:"required"`
    Group  Group  `json:"group" bson:"group"`
    Fields bson.M `json:"fields" bson:"fields"`
}

我遇到的问题是,在Investment模型中,Group字段不是必需的。如果没有group,最好不要将其插入到数据库中。在Go中,处理这样的数据库模型的最佳方法是什么?

英文:

I have two structs that represent models that will be inserted into a mongodb database. One struct (Investment) has the other struct (Group) as one of its fields.

type Group struct {
	Base
	Name string `json:"name" bson"name"`
}

type Investment struct {
	Base
	Symbol string `json:"symbol" bson:"symbol" binding:"required"`
	Group  Group  `json:"group" bson:"group"`
	Fields bson.M `json:"fields" bson:"fields"`
}

The problem I'm having is that in the Investment model, Group is not required. If there is no group, I think its better for it to not be inserted in the db. Whats the best way to handle a db model such as this in Go?

答案1

得分: 77

tl;dr: 使用,omitempty,如果你需要关注零值和null/未指定之间的区别,可以像GitHub API一样使用指针。


jsonbson都支持,omitempty标签。对于json来说,"空值包括false、0、任何nil指针或接口值,以及长度为零的数组、切片、映射或字符串"(json文档)。对于bson来说,,omitempty的意思是"只有在字段未设置为类型的零值或空切片或空映射时才包含该字段",而零值包括空字符串和nil指针(bson文档)。

因此,如果你真的需要一个Group结构体,你可以将*Group放入其中,当指针为nil时它不会被存储。如果Investment只需要保存组的名称,那就更简单了:将""作为组名可以防止组键被存储。

bson默认已经使用小写字段名,所以当它们匹配时,你可以在结构体标签中省略它。json默认使用大写名称,所以如果你需要小写名称,可以在标签中指定小写名称。

所以,最好的情况下,你可以只使用:

type Investment struct {
    Base
    Symbol string `json:"symbol" binding:"required"`
    Group string  `json:"group,omitempty" bson:",omitempty"`
    Fields bson.M `json:"fields"`
}

如果你遇到了类型的零值(例如""、0、false等)与"未指定"不同的字段,你可以像GitHub API一样,在你的结构体中使用指针--本质上是*Group技巧的扩展。

英文:

tl;dr: Use ,omitempty, and if you need to worry about the difference between a zero value and null/not specified, do what the GitHub API does and use a pointer.


Both json and bson support the ,omitempty tag. For json, "empty values are false, 0, any nil pointer or interface value, and any array, slice, map, or string of length zero" (json docs). For bson, ,omitempty means "Only include the field if it's not set to the zero value for the type or to empty slices or maps", and zero values include empty strings and nil pointers (bson docs).

So if you really need a Group struct, you can put a *Group in instead, and it won't be stored when the pointer is nil. If Investment only needs to hold the group's name, it's even simpler: "" as group name keeps a group key from being stored.

bson defaults to using the lowercased field name already so you can omit that from the struct tag when they match. json will default to the Capitalized name, so specify the lowercase name in a tag if you need lowercase.

So, best case, maybe you can just use:

type Investment struct {
    Base
    Symbol string `json:"symbol" binding:"required"`
    Group string  `json:"group,omitempty" bson:",omitempty"`
    Fields bson.M `json:"fields"`
}

If you ever run into fields where the zero value for the type ("", 0, false, etc.) is distinct from "not specified", you can do what the GitHub API does and put pointers in your structures--essentially an extension of the *Group trick.

答案2

得分: 7

避免将空字段转换为 JSON 数据(例如在数据库插入或外部 API 调用中)。

示例:

type Investment struct {
    Base
    Symbol string `json:"symbol,omitempty" bson:"symbol,omitempty" binding:"required"`
    Group  *Group `json:"group,omitempty" bson:"group,omitempty"`
    Fields bson.M `json:"fields" bson:"fields"`
}

如果我们希望 SymbolGroup 可能包含空值(0、false、nil 指针、零大小的接口/结构体),我们可以在 JSON 转换中避免它们。

在这里,"Group" 字段是指向 Group 结构体的指针,当它指向 nil 指针时,它将被省略在 JSON 转换中。

当然,我们会像下面这样填充 Group 字段的值。

// 声明类型为 Investment 的 investment 变量
investment.Group = &groupData
英文:

Avoid strut fields to marshal if they are empty -

A struct field may be primitive type(string, int, bool etc) or even an another struct type.

So sometimes we don't want a struct's field to
go in json data(may to database insertion or in external api call) if they are empty

Example:

> type Investment struct {
> Base
> Symbol string json:"symbol" bson:"symbol" binding:"required"
> Group Group json:"group" bson:"group"
> Fields bson.M json:"fields" bson:"fields"
> }

If we want that Symbol and Group might contain empty values(0, false, nil pointer, zero size interface/struct) then we can avoid them in json marshaling like below.

> type Investment struct {
> Base
> Symbol string json:"symbol,omitempty" bson:"symbol,omitempty" binding:"required"
> Group *Group json:"group,omitempty" bson:"group,omitempty"
> Fields bson.M json:"fields" bson:"fields"
> }

Her "Group" field is pointer to Group struct and whenever it will point to nil pointer it will be omitted from json marshaling.

And obviously we would be filling values in Group field like below.

// declared investment variable of type Investment struct

 investment.Group = &groupData

huangapple
  • 本文由 发表于 2014年6月14日 12:14:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/24216510.html
匿名

发表评论

匿名网友

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

确定