Golang bson结构 - 在json中为单个字段使用多个字段名称,但只有一个用于写入数据库

时间:2016-10-12 06:54:17

标签: json mongodb go struct bson

我有一个像这样的结构 -

type Address struct {
    AddressLine1 string        `json:"addressLine1" bson:"addressLine1"`
    AddressLine2 string        `json:"addressLine2" bson:"addressLine2"`
    Landmark     string        `json:"landmark" bson:"landmark"`
    Zipcode      string        `json:"zipcode" bson:"zipcode"`
    City         string        `json:"city" bson:"city"`
}

由于先前版本和最新尚未发布的版本之间存在一些兼容性问题,我想确保如果有人发布使用此结构解码的json数据,他们应该能够使用'zipcode'或'pincode'作为json中的字段名称。但是当这个值写入我的数据库时,字段名称应该只是'zipcode'。

简而言之,

{
"city": "Mumbai",
"zipcode": "400001"
}

{
"city": "Mumbai",
"pincode": "400001"
}

应该都以 -

的形式出现在数据库中
{
"city": "Mumbai",
"zipcode": "400001"
}

我如何允许这个?

1 个答案:

答案 0 :(得分:1)

您可以将两个字段都指向字符串:

type Address struct {
    AddressLine1 string        `json:"addressLine1" bson:"addressLine1"`
    AddressLine2 string        `json:"addressLine2" bson:"addressLine2"`
    Landmark     string        `json:"landmark" bson:"landmark"`
    Zipcode      *string       `json:"zipcode,omitempty" bson:"zipcode"`
    Pincode      *string       `json:"pincode,omitempty" bson:"zipcode"`
    City         string        `json:"city" bson:"city"`
}

您可能会注意到我们在json标记中使用了 omitempty ,因此如果json中没有其中一个字段,它将被忽略为 nil 指针,在 Marshal() Unmarshal()

之后不会出现

修改

在这种情况下,我们所要做的就是实现方法UnmarshalJSON([]byte) error以满足接口Unmarshaler,方法json.Unmarshal()将始终尝试调用该方法,我们可以添加自己的方法在解组结构之后的逻辑,在这种情况下,如果 pincode 分配给 zipcode ,我们想知道 pincode 是否已解决: 完整示例:https://play.golang.org/p/zAOPMtCwBs

type Address struct {
    AddressLine1 string  `json:"addressLine1" bson:"addressLine1"`
    AddressLine2 string  `json:"addressLine2" bson:"addressLine2"`
    Landmark     string  `json:"landmark" bson:"landmark"`
    Zipcode      *string `json:"zipcode,omitempty" bson:"zipcode"`
    Pincode      *string `json:"pincode,omitempty"`
    City         string  `json:"city" bson:"city"`
}

// private alias of Address to avoid recursion in UnmarshalJSON()
type address Address

func (a *Address) UnmarshalJSON(data []byte) error {
    b := address{}
    if err := json.Unmarshal(data, &b); err != nil {
        return nil
    }
    *a = Address(b) // convert the alias to address

    if a.Pincode != nil && a.Zipcode == nil {
        a.Zipcode = a.Pincode
        a.Pincode = nil // unset pincode
    }

    return nil
}

请注意,字段 Zipcode 有一个bson标记而 Pincode 没有,我们还必须创建一个类型为地址的别名,以避免递归调用UnmarshalJSON