【问题标题】:golang - Rest update request using http patch semanticsgolang - 使用 http 补丁语义的 Rest 更新请求
【发布时间】:2017-06-06 06:56:04
【问题描述】:
type A struct {
    Id int64
    Email sql.NullString
    Phone sql.NullString
}

假设我在数据库中有一条记录

A{1, "x@x.com", "1112223333"}

通过 PUT 发送更新请求

curl -X PUT -d '{"Email": "y@y.com", "Phone": null}' http://localhost:3000/a/1 

这是一个伪算法,它适用于完整的 PUT 请求(即更新记录 A 的所有字段 - 但它会导致 PATCH 请求语义的困难 - 增量更新)

-- 将 json 解组为空记录

  a := A{}
  json.Unmarshal([]byte(request.body), &a)

-- 从数据库中加载记录

aFromDb = <assume we got record from db> //A{1, "x@x.com", "1112223333"}

-- 比较 a 和 aFromDB

-- 注意电子邮件更改并将其设置在 aFromDb 上 - 好的

-- 注意电话号码的变化--但请稍等!它是在 JSON 中明确设置为 NULL 还是甚至没有包含在 JSON 中?即 json 请求 - {"Email": "y@y.com", "Phone": null} 还是 {"Email": "y@y.com"}?

我们如何通过查看结构 a 中未编组的 json 来判断?

是否有另一种方法可以通过 rest 进行更新(使用补丁语义)?我正在寻找一种通用的方法(不依赖于特定的结构)。

【问题讨论】:

    标签: go


    【解决方案1】:

    为此我创建了一个单独的数据类型。此示例适用于 int64(实际上是字符串编码的 int64),但您也可以轻松地将其更改为字符串。它背后的想法是,UnmarshalJSON 方法只有在 JSON 中存在值时才会被调用。该类型将实现MarshalerUnmarshaler

    // Used as a JSON type
    //
    // The Set flag indicates whether an unmarshaling actually happened on the type
    type RequiredInt64 struct {
        Set   bool
        Int64 int64
    }
    
    func (r RequiredInt64) MarshalJSON() ([]byte, error) {
        lit := strconv.FormatInt(r.Int64, 10)
        return json.Marshal(lit)
    }
    
    func (r *RequiredInt64) UnmarshalJSON(raw []byte) error {
        var lit string
        var err error
        if err = json.Unmarshal(raw, &lit); err != nil {
            return err
        }
        r.Int64, err = strconv.ParseInt(lit, 10, 64)
        if err != nil {
            return err
        }
        r.Set = true
        return nil
    }
    

    因此,如果 Set 为 false,则您知道 JSON 中不存在该值。

    【讨论】:

      【解决方案2】:

      尝试将此标签添加到结构中:

      type A struct {
          Id int64 `json:"Id,omitempty"`
          Email sql.NullString `json:"Email,omitempty"`
          Phone sql.NullString `json:"Phone,omitempty"`
      }
      

      这样如果你正在序列化并且字段为空,那么json将不包含该字段。

      当反序列化时,该字段将具有一个值或具有该类型的默认值(指针为 Nil,字符串为空字符串)。

      【讨论】:

      • 谢谢 - 但你能告诉我解组期间这两个不同输入的结构值是什么 - {"Email": "y@y.com", "Phone": null} 和 { “电子邮件”:“y@y.com”}?我们可以从结构上区分两者吗?在一种情况下,客户希望将电话设置为空。在另一种情况下,客户只想更新电子邮件并保持电话完好无损。
      【解决方案3】:

      您可能会编写自己的结构编组/uinmarshalling 并对其中的原始响应做出反应,尽管通过检查这些函数正在操纵什么可能并不明显。

      或者,您不能在字段中省略并强制填充空字段。

      或者,也许利用不同的修补方式,也许是http://jsonpatch.com/,这在修改的性质上更加明确。这将要求客户比看跌期权更了解变化的状态。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-04-20
        • 2021-05-10
        • 2020-05-21
        • 1970-01-01
        • 2022-01-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多