Golang bson 结构 - 在 json 中为单个字段使用多个字段名称,但只有一个用于写入数据库
Golang bson structs - use multiple field names for a single field in json but only one for writing to the database
我有这样的结构 -
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"
}
我如何允许这样做?
您可以将两个字段都作为指向字符串的指针:
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()[=37= 之后不会出现]
编辑:
在这种情况下,我们所要做的就是实现方法 UnmarshalJSON([]byte) error
来满足接口 Unmarshaler,方法 json.Unmarshal()
将始终尝试调用该方法,我们可以添加Unmarshal 结构后我们自己的逻辑,在这种情况下我们想知道 pincode 是否已解决,如果我们分配给 zipcode:
完整示例在这里: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
我有这样的结构 -
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"
}
我如何允许这样做?
您可以将两个字段都作为指向字符串的指针:
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()[=37= 之后不会出现]
编辑:
在这种情况下,我们所要做的就是实现方法 UnmarshalJSON([]byte) error
来满足接口 Unmarshaler,方法 json.Unmarshal()
将始终尝试调用该方法,我们可以添加Unmarshal 结构后我们自己的逻辑,在这种情况下我们想知道 pincode 是否已解决,如果我们分配给 zipcode:
完整示例在这里: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