JSON to struct omitempty PATCH 与 POST 问题

Posted

技术标签:

【中文标题】JSON to struct omitempty PATCH 与 POST 问题【英文标题】:JSON to struct omitempty PATCH versus POST problem 【发布时间】: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将不包含结构中的键。 【参考方案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 := PersonName: "bob"
    json1 := jsoniter.ConfigTagKey: "json1".Froze()
    json2 := jsoniter.ConfigTagKey: "json2".Froze()
    b1, _ := json1.Marshal(&p)
    b2, _ := json2.Marshal(&p)
    fmt.Println(string(b1))
    fmt.Println(string(b2))

输出:

"name":"bob"
"name":"bob","gender":"","nationality":""

【讨论】:

谢谢,我认为这是一个干净的解决方案。

以上是关于JSON to struct omitempty PATCH 与 POST 问题的主要内容,如果未能解决你的问题,请参考以下文章

json.Marshal(struct) 返回“”

golang json omitempty是啥意思

Protocol Buffer 去除 json omitempty

Go结构中omitempty的用例是什么?

ProtoBuf 生成 Go 代码去掉 JSON tag omitempty

ProtoBuf 生成 Go 代码去掉 JSON tag omitempty