英文:
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一样使用指针。
json
和bson
都支持,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"`
}
如果我们希望 Symbol 和 Group 可能包含空值(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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论