How to best normalize JSON data into API structs in Go
php editor Xigua here brings a streamlined guide on how to normalize JSON data into API structures in Go. In modern web applications, working with JSON data is a common task. As a powerful back-end language, Go language provides a concise and flexible way to process JSON data. This article will introduce how to use structures in the Go language to normalize JSON data so that they can be better processed and manipulated. Whether you are a beginner or an experienced developer, this article will provide you with useful tips and practical examples. let's start!
Question content
I am fairly new to go and am trying to determine if there is a cleaner way to accomplish the normalization of json data from the front end (js) to my api. To ensure that the correct types are used when creating variables from the struct (model.expense), I dump the payload into a map, then normalize and save back to the struct. If anyone could teach me a better way to handle this I would be very grateful! Thanks in advance!
Model. Fee structure:
type expense struct { id primitive.objectid `json:"_id,omitempty" bson:"_id,omitempty"` name string `json:"name"` frequency int `json:"frequency"` startdate *time.time `json:"startdate"` enddate *time.time `json:"enddate,omitempty"` cost primitive.decimal128 `json:"cost"` paid []string `json:"paid,omitempty"` }
Problematic controller:
func InsertOneExpense(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") w.Header().Set("Allow-Control-Allow-Methods", "POST") var expense map[string]interface{} json.NewDecoder(r.Body).Decode(&expense) var expenseName string if name, ok := expense["name"]; ok { expenseName = fmt.Sprintf("%v", name) } else { json.NewEncoder(w).Encode("missing required name") } var expenseFrequency int if frequency, ok := expense["frequency"]; ok { expenseFrequency = int(frequency.(float64)) } else { expenseFrequency = 1 } // Handle startDate normalization var expenseStartDate *time.Time if startDate, ok := expense["startDate"]; ok { startDateString := fmt.Sprintf("%v", startDate) startDateParsed, err := time.Parse("2006-01-02 15:04:05", startDateString) if err != nil { log.Fatal(err) } expenseStartDate = &startDateParsed } else { json.NewEncoder(w).Encode("missing required startDate") } // Handle endDate normalization var expenseEndDate *time.Time if endDate, ok := expense["endDate"]; ok { endDateString := fmt.Sprintf("%v", endDate) endDateParsed, err := time.Parse("2006-01-02 15:04:05", endDateString) if err != nil { log.Fatal(err) } expenseEndDate = &endDateParsed } else { expenseEndDate = nil } // Handle cost normaliztion var expenseCost primitive.Decimal128 if cost, ok := expense["cost"]; ok { costString := fmt.Sprintf("%v", cost) costPrimitive, err := primitive.ParseDecimal128(costString) if err != nil { log.Fatal(err) } expenseCost = costPrimitive } else { json.NewEncoder(w).Encode("missing required cost") return } normalizedExpense := model.Expense{ Name: expenseName, Frequency: expenseFrequency, StartDate: expenseStartDate, EndDate: expenseEndDate, Cost: expenseCost, } // Do more things with the struct var... }
Workaround
You can define the json.unmarshaljson
interface and then manually validate the data if needed. Try something like this:
package main import ( "encoding/json" "fmt" "strconv" ) type CoolStruct struct { MoneyOwed string `json:"money_owed"` } // UnmarshalJSON the json package will delegate deserialization to our code if we implement the json.UnmarshalJSON interface func (c *CoolStruct) UnmarshalJSON(data []byte) error { // get the body as a map[string]*[]byte raw := map[string]*json.RawMessage{} if err := json.Unmarshal(data, &raw); err != nil { return fmt.Errorf("unable to unmarshal raw meessage map: %w", err) } // if we don't know the variable type sent we can unmarshal to an interface var tempHolder interface{} err := json.Unmarshal(*raw["money_owed"], &tempHolder) if err != nil { return fmt.Errorf("unable to unmarshal custom value from raw message map: %w", err) } // the unmarshalled interface has an underlying type use go's typing // system to determine type conversions / normalizations required switch tempHolder.(type) { case int64: // once we determine the type of the we just assign the value // to the receiver's field c.MoneyOwed = strconv.FormatInt(tempHolder.(int64), 10) // we could list all individually or as a group; driven by requirements case int, int32, float32, float64: c.MoneyOwed = fmt.Sprint(tempHolder) case string: c.MoneyOwed = tempHolder.(string) default: fmt.Printf("missing type case: %T\n", tempHolder) } // success; struct is now populated return nil } func main() { myJson := []byte(`{"money_owed": 123.12}`) cool := CoolStruct{} // outside of your struct you marshal/unmarshal as normal if err := json.Unmarshal(myJson, &cool); err != nil { panic(err) } fmt.Printf("%+v\n", cool) }
Output: {moneyowed:123.12}
Playground link: https://www.php.cn/link/87ca4eb840b6f78e3b6d6b418c0fef40
The above is the detailed content of How to best normalize JSON data into API structs in Go. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics











The problem of using RedisStream to implement message queues in Go language is using Go language and Redis...

Queue threading problem in Go crawler Colly explores the problem of using the Colly crawler library in Go language, developers often encounter problems with threads and request queues. �...

What should I do if the custom structure labels in GoLand are not displayed? When using GoLand for Go language development, many developers will encounter custom structure tags...

The difference between string printing in Go language: The difference in the effect of using Println and string() functions is in Go...

The library used for floating-point number operation in Go language introduces how to ensure the accuracy is...

Two ways to define structures in Go language: the difference between var and type keywords. When defining structures, Go language often sees two different ways of writing: First...

Which libraries in Go are developed by large companies or well-known open source projects? When programming in Go, developers often encounter some common needs, ...

When using sql.Open, why doesn’t the DSN report an error? In Go language, sql.Open...
