JSON转结构体omitempty PATCH与POST问题

huangapple go评论87阅读模式
英文:

JSON to struct omitempty PATCH versus POST problem

问题

我正在设计一些使用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中存在。然而,当我要对JSON序列化使用omitempty标签时,我无法强制POST请求包含所有字段,而PATCH请求只包含字段的子集。

英文:

I am designing some REST API endpoints in Go. I use structs to define the object that handling in my API methods. These objects are sent as json and are stored in Firebase. Suppose I have the following simple struct:

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

And I have the following requirements:

  • All fields are required when doing a GET request and reading from firebase.
  • All fields are required when doing a POST request and serializing json body to struct.
  • Only the Name field is required when doing a PATCH request and serializing json body to struct.

What is the cleanest way to do serialization based on the same struct for all the methods? When doing the GET request there is no problem, since all the fields are and need to be present in Firebase. However, when I am going to use the omitempty tag for json serialization I cannot force the POST request to contain all fields and the PATCH request to contain only a subset of fields.

答案1

得分: 1

你可以实现自定义的编组接口(custom marshal interface),或者使用第三方库,比如 https://github.com/json-iterator/go,它支持自定义的 JSON 标签。

以下是示例代码:

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":""}

希望对你有帮助!

英文:

You could implement custom marshal interface or use a 3rd party lib like https://github.com/json-iterator/go which support custom json tag

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

output:

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

答案2

得分: 0

我会为你翻译以下内容:

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

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

// ValidatePost 验证结构体是否包含所有必填字段的值(用于 POST 操作)
func (p Person) ValidatePost() bool {
    if p.Name == "" || p.Gender == "" || p.Nationality == "" {
        return false
    }
    return true
}

// ValidatePatch 验证结构体是否包含所有必填字段的值(用于 PATCH 操作)
func (p Person) ValidatePatch() bool {
    if p.Name == "" {
        return false
    }
    return true
}
英文:

I would probably write a validation function.

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
}

huangapple
  • 本文由 发表于 2021年10月17日 18:21:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/69603328.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定