【问题标题】:JSON to struct omitempty PATCH versus POST problemJSON to struct omitempty PATCH 与 POST 问题
【发布时间】:2021-12-04 18:09:41
【问题描述】:

我正在用 Go 设计一些 REST API 端点。我使用结构来定义在我的 API 方法中处理的对象。这些对象以 json 格式发送并存储在 Firebase 中。假设我有以下简单的结构:

type Person struct {
  Name        string `json:"name" firestore:"name"`
  Gender      string `json:"gender,omitempty" firestore:"gender"`
  Nationality string `json:"nationality,omitempty" firestore:"nationality"`
}

而且我有以下要求:

  • 在执行 GET 请求并从 firebase 读取时,所有字段都是必需的。
  • 在执行 POST 请求并将 json 正文序列化为结构时,所有字段都是必需的。
  • 在执行PATCH 请求并将json 正文序列化为结构时,只需要Name 字段。

对于所有方法,基于相同结构进行序列化的最简洁方法是什么?执行GET 请求时没有问题,因为所有字段都存在并且需要存在于 Firebase 中。但是,当我要使用 omitempty 标记进行 json 序列化时,我无法强制 POST 请求包含所有字段,而 PATCH 请求仅包含字段子集。

【问题讨论】:

  • 为补丁定义不同的模型结构对我来说似乎足够干净。想要重用相同的Person 模型是否有特殊原因?或者你的意思是补丁可能还包含其他字段,但只要求Name
  • 我认为“omitempty”标签仅用于将结构编组为 JSON 的情况,这意味着如果您解组一个空的 json 字符串,您将获得具有零值的结构。因此,对于 GET 请求,您将获得从数据库填充的值或默认的零值,并且您将在下游为它们提供服务。这里“omitempty”标签发挥作用:如果它被设置,如果值是零值,生成的json将不包含结构中的键。

标签: json http go struct


【解决方案1】:

我可能会写一个验证函数。

type Person struct {
    Name        string `json:"name" firestore:"name"`
    Gender      string `json:"gender,omitempty" firestore:"gender"`
    Nationality string `json:"nationality,omitempty" firestore:"nationality"`
}

// ValidatePost validates the struct contains values for all mandatory fields for POST operations
func (p Person) ValidatePost()bool  {
    if p.Name =="" || p.Gender == "" || p.Nationality == ""{
        return false
    }
    return true
}

// ValidatePatch validates the struct contains values for all mandatory fields for PATCH operations
func (p Person) ValidatePatch()bool  {
    if p.Name =="" {
        return false
    }
    return true
}

【讨论】:

    【解决方案2】:

    您可以实现custom marshal 接口或使用支持自定义json 标签的https://github.com/json-iterator/go 等第三方库

    package main
    
    import (
        "fmt"
    
        jsoniter "github.com/json-iterator/go"
    )
    
    type Person struct {
        Name        string `json1:"name" json2:"name"`
        Gender      string `json1:"gender,omitempty" json2:"gender"`
        Nationality string `json1:"nationality,omitempty" json2:"nationality"`
    }
    
    func main() {
        p := Person{Name: "bob"}
        json1 := jsoniter.Config{TagKey: "json1"}.Froze()
        json2 := jsoniter.Config{TagKey: "json2"}.Froze()
        b1, _ := json1.Marshal(&p)
        b2, _ := json2.Marshal(&p)
        fmt.Println(string(b1))
        fmt.Println(string(b2))
    }
    

    输出:

    {"name":"bob"}
    {"name":"bob","gender":"","nationality":""}
    

    【讨论】:

    • 谢谢,我认为这是一个干净的解决方案。
    猜你喜欢
    • 1970-01-01
    • 2023-01-13
    • 1970-01-01
    • 1970-01-01
    • 2020-07-08
    • 1970-01-01
    • 1970-01-01
    • 2011-11-17
    • 1970-01-01
    相关资源
    最近更新 更多