Rest golang中如何处理未设置值的补丁请求

Rest golang中如何处理未设置值的补丁请求,rest,go,patch,go-gorm,Rest,Go,Patch,Go Gorm,我正在处理一个补丁restful请求,请求主体json在发送到golang时包含一些省略的值。由于未设置的值将导致golang结构成为默认值。所以我想知道是否有任何解决方案来处理补丁请求忽略数据 正如我所知,像string/int这样的基本类型在golang中不能为null。有不同的方法来处理未设置值的补丁请求。例如: 用指针处理空值问题 type User struct { Name *string } 使用可空库 type User struct { Name sql.

我正在处理一个补丁restful请求,请求主体json在发送到golang时包含一些省略的值。由于未设置的值将导致golang结构成为默认值。所以我想知道是否有任何解决方案来处理补丁请求忽略数据

正如我所知,像string/int这样的基本类型在golang中不能为null。有不同的方法来处理未设置值的补丁请求。例如:

  • 用指针处理空值问题

    type User struct {
        Name *string
    }
    
  • 使用可空库

    type User struct {
        Name  sql.NullString
    }
    
  • 使用
    map[string][]接口{}
    查看是否设置了值


  • 有没有更好的解决方案来处理struct内部的可空值?因为这3应该是处理可空值的变通方法

    将指针与
    ommitempty
    标记一起使用。通过这种方式,您可以区分未设置的值nil和有意设置的零值(“,false,0)


    另一个解决方案是编写自己的类型,并实现

    结果是
    {Data1:{Data:Null:true}Data2:{Data:string Null:false}Data3:{Data:Null:false}
    如果值是
    Null
    ,则设置Null字段。如果需要,您也可以简单地向这个结构添加额外的字段。例如,要跟踪函数是否被调用的字段

    ps:另请参见从struct到json的反向


    如果您以RESTful方式使用
    补丁
    ,这意味着它正在更新一些现有数据,并且只覆盖请求正文中包含的字段。这意味着您实际上不需要知道是否设置了哪些字段;您只需加载规范对象并在其上解组即可替换JSON中找到的任何字段,同时保留任何其他字段不变:

    canonObj := getObjectFromDBOrSomething()
    err := json.NewDecoder(req.Body).Decode(canonObj)
    

    这将使用请求中的字段覆盖
    cannobj
    中的任何字段,但不会触及请求中未包含的任何字段。

    谢谢您的建议。是的,这是一种可行的方法。但我想知道有什么理由不建议使用nullable lib?p、 我在考虑哪种解决方案更好,但不知道哪种更好。嗯,这是另一种依赖。我不知道这对你来说是否是个问题。我建议它是标准的(不需要libs)。考虑到指针是语言内置的可空(嗯,
    nil
    able)类型,使用第三方库似乎有点愚蠢。你是对的,使用第三方库来完成这种任务真的很愚蠢。。。我应该考虑使用指针,唯一的另一种可能性是,如果您有希望修补已经加载的值,例如从DB中,您可以解封到该值中,JSON中省略的字段不会被覆盖在该值上。这个方法真的很神奇,没有意识到我们可以这样做。不要忘记传递地址(
    &cannobj
    ),因为它可能不是指针。如果不是指针,就传递地址。如果它已经是指针,请按原样传递它。如果您希望客户端更新
    cannobj
    中的任何字段,这是一个很好的解决方案。如果存在不能更新的字段(例如
    id
    ),该怎么办。我觉得上面的@hlscalon答案在这种情况下是有意义的,除非我遗漏了一些东西。
    getobjectfromdb或某些东西
    可能会很昂贵。最好使用@hlscalon的答案,以便在从数据库中提取数据之前验证结构。如果它符合您的用例,那么这是一个很好的提示。
    package main
    
    import (
        "encoding/json"
        "fmt"
    )
    
    type NullString struct {
        Data string
        Null bool
    }
    
    func (ns *NullString) UnmarshalJSON(d []byte) error {
        if string(d) == "null" {
            // this is based on your need. you may add a new field here
            ns.Null = true
            return nil
        }
        return json.Unmarshal(d, &ns.Data)
    }
    
    type Test struct {
        Data1 NullString `json:"data1"`
        Data2 NullString `json:"data2"`
        Data3 NullString `json:"data3"`
    }
    
    const t = `{"data1":null, "data2":"string"}`
    
    func main() {
        p := Test{}
        json.Unmarshal([]byte(t), &p)
        fmt.Printf("%+v", p)
    }
    
    canonObj := getObjectFromDBOrSomething()
    err := json.NewDecoder(req.Body).Decode(canonObj)