如何最好地将 JSON 数据规范化为 Go 中的 API 结构体

2024年 2月 13日 63.5k 0

如何最好地将 json 数据规范化为 go 中的 api 结构体

php小编西瓜在这里带来了一篇关于如何将JSON数据规范化为Go中的API结构体的精简指南。在现代Web应用程序中,与JSON数据打交道是常见的任务。Go语言作为一门强大的后端语言,提供了一种简洁而灵活的方式来处理JSON数据。本文将介绍如何使用Go语言中的结构体来规范化JSON数据,从而更好地处理和操作它们。无论你是初学者还是有经验的开发人员,本文都将为你提供有用的技巧和实用的示例。让我们开始吧!

问题内容

我对 go 还很陌生,正在尝试确定是否有更简洁的方法来完成从前端 (js) 到我的 api 的 json 数据的规范化。为了确保在从结构 (model.expense) 创建变量时使用正确的类型,我将有效负载转储到映射中,然后规范化并保存回结构。如果有人可以教我更好的方法来处理这个问题,我将不胜感激!提前致谢!

模型.费用结构:

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

登录后复制

有问题的控制器:

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

登录后复制

解决方法

您可以定义 json.unmarshaljson 接口,然后根据需要手动验证数据。尝试这样的事情:

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: %Tn", 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("%+vn", cool)
}

登录后复制

输出:{moneyowed:123.12}
游乐场链接:https://www.php.cn/link/87ca4eb840b6f78e3b6d6b418c0fef40

以上就是如何最好地将 JSON 数据规范化为 Go 中的 API 结构体的详细内容,更多请关注每日运维网(www.mryunwei.com)其它相关文章!

相关文章

JavaScript2024新功能:Object.groupBy、正则表达式v标志
PHP trim 函数对多字节字符的使用和限制
新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
为React 19做准备:WordPress 6.6用户指南
如何删除WordPress中的所有评论

发布评论