dtqi87613 2016-10-12 06:54
浏览 657
已采纳

Golang Bson结构-对JSON中的单个字段使用多个字段名称,但仅将一个字段用于写入数据库

I have a struct like this -

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"`
}

Due to some compatibility issues between the previous build and the latest yet-to-be-released build, I want to make sure that if someone posts json data that decodes using this struct they should be able to use either 'zipcode' or 'pincode' as the field name in their json. But when this value is written to my database, the field name should only be 'zipcode'.

In short,

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

or

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

should both appear inside the database as -

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

How do I allow this?

  • 写回答

1条回答 默认 最新

  • duanbin3021 2016-10-12 07:17
    关注

    You can have both fields as pointer to string:

    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"`
    }
    

    As you may note we're using omitempty in the json tag, so if one of the fields is not present in the json it will be ignored as a nil pointer and it will not be present after Marshal() or Unmarshal()

    Edit:

    In this case all we have to do is implement the method UnmarshalJSON([]byte) error to satisfy the interface Unmarshaler, the method json.Unmarshal() will always try to call that method and we can add our own logic after Unmarshal the struct, in this case we want to know if pincode is settled if it's we assigned to zipcode: full example here: 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
    }
    

    Note that the field Zipcode has a bson tag and Pincode not, also we have to create an alias of type address to avoid calling UnmarshalJSON recursively

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥60 版本过低apk如何修改可以兼容新的安卓系统
  • ¥25 由IPR导致的DRIVER_POWER_STATE_FAILURE蓝屏
  • ¥50 有数据,怎么建立模型求影响全要素生产率的因素
  • ¥50 有数据,怎么用matlab求全要素生产率
  • ¥15 TI的insta-spin例程
  • ¥15 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题
  • ¥15 请完成下列相关问题!
  • ¥15 drone 推送镜像时候 purge: true 推送完毕后没有删除对应的镜像,手动拷贝到服务器执行结果正确在样才能让指令自动执行成功删除对应镜像,如何解决?