golang - 使用http补丁语义进行休息更新请求

时间:2014-05-22 23:34:19

标签: go

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 

这是 psuedo算法,它可以处理完整的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请求 - {“电子邮件”:“y @ y.com”,“电话”:null}或者它是{“电子邮件”:“y@y.com”}?

我们怎样才能通过查看unmarshaled json进入struct a?

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

3 个答案:

答案 0 :(得分:0)

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

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

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

虽然反序列化虽然该字段将具有值或者它将具有该类型的默认值(指针为Nil或字符串为空字符串)。

答案 1 :(得分:0)

我为此创建了一个单独的数据类型。此示例适用于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中。

答案 2 :(得分:0)

您可以编写自己的结构编组/ uinmarshalling并对内部的原始响应做出反应,尽管检查这些函数正在操作的内容可能并不明显。

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

或者,也许可以利用不同的修补方式,也许是http://jsonpatch.com/,这在修改的性质上更为明确。这将要求客户更多地了解变化的状态,而不是对put的理解。