Home > other >  JSON to struct omitempty PATCH versus POST problem
JSON to struct omitempty PATCH versus POST problem

Time:10-18

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.

CodePudding user response:

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
}

CodePudding user response:

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