[英]Golang unmarshal JSON response, then convert the field name into snake_case
我想獲取帶有 json 標簽的數據,其來源具有 PascalCase 格式並將其保存到我的數據庫中。 但是在進入數據庫之前,我想將 PascalCase 格式更改為 snake_case 格式。
我的問題似乎與這個問題相反( Golang Unmarshal an JSON response, then marshal with Struct field names )。 但是我不想使用 PascalCase,而是希望在名稱字段中使用 snake_case
這是我寫的示例代碼:
package main
import (
"encoding/json"
"log"
)
// models data to save in DB
type (
Person struct {
FirstName string `json:"FirstName"`
LastName string `json:"LastName"`
Children []ChildData `json:"Children,omitempty"`
}
ChildData struct {
ChildName string `json:"ChildName"`
Age int `json:"Age"`
FavColor string `json:"FavColor"`
}
PersonOut struct {
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
Children []ChildData `json:"children,omitempty"`
}
ChildDataOut struct {
ChildName string `json:"child_name"`
Age int `json:"age"`
FavColor string `json:"fav_Color"`
}
)
// grisha is data from fetch API
var grisha = map[string]interface{}{
"FirstName": "Grisha",
"LastName": "Jeager",
"Children": []map[string]interface{}{
{
"ChildName": "Zeke",
"Age": 2,
"FavColor": "blue",
}, {
"ChildName": "Eren",
"Age": 3,
"FavColor": "red",
},
},
}
func getJsonfromAPI(data map[string]interface{}) []byte {
grishaJson, _ := json.MarshalIndent(grisha, "", " ")
return grishaJson
}
func parsingJSON(jsonInput []byte) {
var person Person
json.Unmarshal(jsonInput, &person)
out := PersonOut(person)
payload2, err := json.MarshalIndent(out, "", " ")
if err != nil {
panic(err)
}
log.Println(string(payload2))
}
func main() {
data := getJsonfromAPI(grisha)
parsingJSON(data)
}
我想要的結果就像
{
"first_name": "Grisha",
"last_name": "Jeager",
"children": [
{
"child_name": "Zeke",
"age": 2,
"fav_color": "blue"
},
{
"child_name": "Eren",
"age": 3,
"fav_color": "red"
}
]
}
但結果在嵌套字段中仍然有 PascalCase:
{
"first_name": "Grisha",
"last_name": "Jeager",
"children": [
{
"ChildName": "Zeke",
"Age": 2,
"FavColor": "blue"
},
{
"ChildName": "Eren",
"Age": 3,
"FavColor": "red"
}
]
}
我想知道如何從解組 JSON 轉換嵌套結構的字段名稱。
只有當它們的基礎類型(忽略標簽)相同時,將一個結構轉換為另一個結構才有效。 如果基礎類型不相同,則無法進行轉換。
以結構S1
和S2
為例,在下面的代碼片段中,它們的基礎類型是相同的,您可以將一個轉換為另一個:
type S1 struct {
Field T1
}
type S2 struct {
Field T1
}
type T1 string
_ = S2(S1{}) // ok
但是,在下一個片段中,它們的基礎類型並不相同,因此您不能將一個轉換為另一個:
type S1 struct {
Field T1
}
type S2 struct {
Field T2
}
type T1 string
type T2 string
_ = S2(S1{}) // cannot convert S1{} (value of type S1) to type S2
有關更多詳細信息,請閱讀此處的轉換規范: https://go.dev/ref/spec#Conversions
因此,要在基礎類型不相同的兩個結構之間進行轉換,您必須逐個字段手動進行轉換。 但是,在 JSON 封送處理的情況下,您可以通過實現json.Marshaler
接口並讓各個實例“自我轉換”來使它更好一些。
type Person struct {
FirstName string `json:"FirstName"`
LastName string `json:"LastName"`
Children []ChildData `json:"Children"`
}
func (p Person) MarshalJSON() ([]byte, error) {
type T struct {
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
Children []ChildData `json:"children"`
}
return json.Marshal(T(p))
}
type ChildData struct {
ChildName string `json:"ChildName"`
Age int `json:"Age"`
FavColor string `json:"FavColor"`
}
func (d ChildData) MarshalJSON() ([]byte, error) {
type T struct {
ChildName string `json:"child_name"`
Age int `json:"age"`
FavColor string `json:"fav_color"`
}
return json.Marshal(T(d))
}
https://go.dev/play/p/l4O8KBNrm1T
我們需要:
func childDataToChildDataOut(childData ChildData) ChildDataOut {
return ChildDataOut{
ChildName: childData.ChildName,
Age: childData.Age,
FavColor: childData.FavColor,
}
}
func personToPersonOut(person Person) PersonOut {
var children []ChildDataOut
for _, childData := range person.Children {
childDataOut := childDataToChildDataOut(childData)
children = append(children, childDataOut)
}
return PersonOut{
FirstName: person.FirstName,
LastName: person.LastName,
Children: children,
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.