如何在Golang中处理具有未设置值的补丁请求

如何在Golang中处理具有未设置值的补丁请求

问题描述:

I am working on a patch restful request that the body json contain some omitted value while sending to golang. Since an unset value will lead the golang struct become default value. So I would like to know if there are any solution to deal with patch request omit data?

As I know, a basic type like string / int cannot be nullable in golang. there are different approach to deal with unset value patch request. For example:

  1. using pointer to deal with null problem

    type User struct {
        Name *string
    }
    
  2. using nullable library

    type User struct {
        Name  sql.NullString
    }
    
  3. using map[string][]interface{} to see if the value is set

Is there any better solution to deal with nullable value inside struct? since this 3 should be work around to deal with the nullable value.

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

据我所知,像string / int这样的基本类型在golang中不能为空。 有多种处理未设置值补丁请求的方法。 例如: p>

  1. 使用指针处理空问题 p>

      type用户结构{
    名称 * string 
    } 
      code>  pre>  li> 
     
  2. 使用可空库 p>

      type用户结构{
     使用 map [string] [] interface {}  code>命名sql.NullString 
    } 
      code>  pre>  li> \ li> 
     
  3. p> 设置了值 p> li> ol>

    是否有更好的解决方案来处理struct中的可空值? 因为应该处理此3以处理可为空的值。 p> div>

Use a pointer along with the omitempty tag. This way you can differentiate between an unset value, nil, and an intentional zero value ("", false, 0).

type User struct {
    Name *string `json:"name,omitempty"`
}

Playground

Another solution is writing your own type, and implement json.Unmarshaller

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)
}

result is {Data1:{Data: Null:true} Data2:{Data:string Null:false} Data3:{Data: Null:false}} if the value is null then the Null field is set. also you can simply add extra fields to this struct if needed. for example a field to track if the function is called or not.

ps : also see the json.Marshaller for the reverse from struct to json.

playground

If you're using PATCH in a RESTful way, that means it's updating some existing data, and only overwriting those fields included in the request body. Which means you don't actually need to know which fields are set or not; you can just load your canonical object and unmarshal over it to replace any fields that are found in the JSON, while leaving any others untouched:

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

This will overwrite any fields in canonObj with fields from the request, but any fields not in the request won't be touched.