REST API通过部分json更新

时间:2019-02-20 04:29:05

标签: json rest go

我们正在使用Golang来实现包括CRUD在内的REST API,在Update服务中,客户端可以发送包括已更改字段的部分JSON,因此我们需要处理通过这些更改来更新实体。

从逻辑上讲,我们需要通过ID从数据库获取实体到结构,然后将有效载荷json解组到另一个结构并更新实体。

但是如果有效负载json不完整,例如我有struct

type Customer struct {
    Id      int64 `json:"id"`
    Name    string `json:"name"`
    Age     int `json:"age"`
}

JSON请求看起来像

{
  "Name": "Updated name"
}

然后应使用新名称更新客户。

这是一个简单的示例,实际上它可能是一个嵌套的结构和一个嵌套的json,我们如何用golang或事件其他语言(如Java,.NET)处理这种情况

2 个答案:

答案 0 :(得分:2)

如果Update请求使用相同的Customer结构,则结构字段可以是用于区分零值和未在JSON中设置的值的指针。
现在,您需要做的就是将现有结构合并到更新的Consumer结构中。
为此,您可以在Go中使用https://github.com/imdario/mergo库。

package main

import (
    "fmt"
    "github.com/imdario/mergo"
    "encoding/json"
    "os"
)

type Address struct {
    City string `json:"city"`
}

type Customer struct {
    Id      int64 `json:"id"`
    Name    string `json:"name"`
    Age     int `json:"age"`
    Address *Address `json:"address"`
}


func main() {
    old1 := &Customer{Id:1, Name:"alpha", Age:5, Address:&Address{City:"Delhi"}}

    b := []byte(`{"name": "beta"}`) //no address, age specified picks from old
    up1 := new(Customer)
    json.Unmarshal(b, up1)
    if err := mergo.Merge(up1, old1); err != nil {
        fmt.Printf("err in 1st merge: %v\n", err)
        os.Exit(1)
    }
    m1, _ := json.Marshal(up1)
    fmt.Printf("merged to: %v\n", string(m1))

    old2 := &Customer{Id:1, Name:"alpha", Age:5, Address:&Address{City:"Delhi"}}
    b2 := []byte(`{ "address": {"city": "mumbai"}}`) //address specified
    up2 := new(Customer)
    json.Unmarshal(b2, up2)
    if err := mergo.Merge(up2, old2); err != nil {
        fmt.Printf("err in 1st merge: %v\n", err)
        os.Exit(1)
    }
    m2, _ := json.Marshal(up2)
    fmt.Printf("merged to: %v\n", string(m2))
}

答案 1 :(得分:0)

从您的评论中看来,您遇到了许多go用户,即零值问题,即如何判断输入数据是否传递了合法值-或该值默认为零。

解决此问题的唯一方法是使用指针。因此,在您的示例中,将数据结构更改为此:

type Customer struct {
    Id   *int64  `json:"id"`
    Name *string `json:"name"`
    Age  *int    `json:"age"`
}

然后在取消编组后,所有未初始化的字段都将具有nil值,例如

var c Customer

err := json.Unmarshal(jsonData, &c)
if err != nil {
    panic(err)
}

if c.Id != nil {
    log.Println("TODO: added SQL update parms for c.Id:", *c.Id)
}
if c.Name != nil {
    log.Println("TODO: added SQL update params for c.Name:", *c.Name)
}
if c.Age != nil {
    log.Println("TODO: added SQL update parms for c.Age:", *c.Age)
}

注意:必须注意确保不会意外引用任何会触发即时panic的nil指针。

工作playground example