用HTTP Patch语义进行Golang Rest更新请求

3
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 后就能判断呢?

是否有另一种使用 REST 进行更新的方法(具有修补程序语义)?我正在寻找一种通用的方式来实现它(不绑定到特定的结构体)。

3个回答

1
我为此创建了一个单独的数据类型。这个示例是针对int64(实际上是字符串编码的int64),但你也可以轻松地将其更改为字符串。其背后的想法是,只有在JSON中存在该值时,才会调用UnmarshalJSON方法。该类型将实现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 中不存在。

0

尝试将这些标签添加到结构体中:

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} 和 {"Email": "y@y.com"}?我们能从结构体中区分这两种情况吗?在一个案例中,客户想将电话设置为null。在另一个案例中,客户只想更新电子邮件并保留电话不变。 - sat

0

你可以潜在地编写自己的结构体编组/解组,并在其中对原始响应进行反应,尽管通过检查可能不明显这些函数正在操作什么。

或者,您可以不在字段中使用omitempty并强制使用空值填充字段。

或者,也许利用不同类型的修补程序,比如http://jsonpatch.com/,它更明确地说明了您的修改性质。这将要求客户端比put更理解变化的状态。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接