如何在Golang结构中使用omitempty标志更新Mongodb字段

时间:2017-11-07 13:18:08

标签: json mongodb forms go struct

我正在使用优惠券表单,其中我有一些可选字段。

简介

所有表单字段值都以JSON格式接收并映射到Golang结构中。在结构中,我为每个字段添加了“omitempty”标志。因此,只有那些具有一些适当值的表单值被映射,其余的值如0,“”,false将被结构忽略。

这是Golang结构

type Coupon struct {
    Id               int    `json:"id,omitempty" bson:"_id,omitempty"`
    Name             string `json:"name,omitempty" bson:"name,omitempty"`
    Code             string `json:"code,omitempty" bson:"code,omitempty"`
    Description      string `json:"description,omitempty" bson:"description,omitempty"`
    Status           bool   `json:"status" bson:"status"`
    MaxUsageLimit    int    `json:"max_usage_limit,omitempty" bson:"max_usage_limit,omitempty"`
    SingleUsePerUser bool   `json:"single_use_per_user,omitempty" bson:"single_use_per_user,omitempty"`
}

问题:

  1. 当我第一次保存此表单时,相应的表单值将保存到Mongodb中。

  2. 现在我想更新该表单,并假设有一个复选框,在保存数据时已选中该复选框。更新表单时,将取消选中该复选框,并提交表单进行保存。现在我在结构中应用了“omitempty”标志,因此它不将空值映射到复选框字段。由于该值未映射到结构中,因此不会将其保存到数据库中。

  3. 当用户第二次编辑表单时,它会看到与选中相同的复选框。 (但实际上,该值应更新为DB,复选框应显示为未选中。)

  4. 我在REST API中使用相同的表单数据(JSON格式)。在API中,在更新表单数据时,如果我只提到那些需要的值并且不传递我不想更新的值,那么MongoDB会使用提供的所需值覆盖整个文档(即使这些值是也被覆盖,我不想更新,也不传递API)。

  5. 要求:

    将来,我想公开REST API,所以我不希望这件事发生在那里。这就是为什么我不想从结构字段中删除“omitempty”标志。

    在结构中使用omitempty标志时,有没有办法将空表单值或API数据字段保存到数据库?

    谢谢!

2 个答案:

答案 0 :(得分:3)

bool类型有两个可能的值:falsetrue。并且您希望使用bool字段“通信”3个不同的状态,即不更新字段,将字段设置为false并将字段设置为true。这显然是不可能的。

同样适用于int值:0的值不能代表2种不同的选择,即不更新字段并将其设置为0

如果您想在标记值中保留omitempty选项,那么为了使其有效,您必须将字段更改为指针:

type Coupon struct {
    Id               *int    `json:"id,omitempty" bson:"_id,omitempty"`
    Name             string `json:"name,omitempty" bson:"name,omitempty"`
    Code             string `json:"code,omitempty" bson:"code,omitempty"`
    Description      string `json:"description,omitempty" bson:"description,omitempty"`
    Status           *bool   `json:"status" bson:"status"`
    MaxUsageLimit    *int    `json:"max_usage_limit,omitempty" bson:"max_usage_limit,omitempty"`
    SingleUsePerUser *bool   `json:"single_use_per_user,omitempty" bson:"single_use_per_user,omitempty"`
}

它的工作方式是,如果指针是nil,它将被省略(这是“omitempty”选项)。如果该字段是非nil指针,则它将更新为指向的值。

例如,如果您要排除bool字段,则*bool值应为/ nil。如果要将其设置/更新为false,则它必须是指向false值的指针。如果要将其设置/更新为true,则它必须是指向true值的指针。

一般情况下,任何zero value都可以并且应该被计算的类型,如果你把它作为一个指针,你只能处理“它是零值”和“它从输入中丢失” ,并且指针的nil值将表示“从输入中丢失”的情况,而指向零值的非nil指针将表示“它是零值”的情况。因此,在上面的示例中,如果string字段也可以采用空字符串值(""),那么您还必须使它们成为指针。

请注意,您也可以使用自定义编组和解组逻辑来实现此目的,但这更麻烦,使用指针会自动为您提供此功能。

答案 1 :(得分:0)

您应该使用指针使用omitempty,如下所示

type Coupon struct {
    Id               int    `json:"id,omitempty" bson:"_id,omitempty"`
    Name             string `json:"name,omitempty" bson:"name,omitempty"`
    Code             *string `json:"code,omitempty" bson:"code,omitempty"`
    Description      string `json:"description,omitempty" bson:"description,omitempty"`
    Status           *bool   `json:"status" bson:"status"`
    MaxUsageLimit    int    `json:"max_usage_limit,omitempty" bson:"max_usage_limit,omitempty"`
    SingleUsePerUser bool   `json:"single_use_per_user,omitempty" bson:"single_use_per_user,omitempty"`
}

有一篇很好的文章可以解释积分如何运作https://willnorris.com/2014/05/go-rest-apis-and-pointers