Golang 解组 JSON 响应,然后将字段名称转换为 snake_case
Golang unmarshal JSON response, then convert the field name into snake_case
我想获取带有 json 标签的数据,其来源是 PascalCase 格式,并将其保存到我的数据库中。但是在进入数据库之前,我想将 PascalCase 格式更改为 snake_case 格式。
我的问题好像和这个问题相反()。但是我不想使用 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
我们需要:
- 将 Person 映射到 PersonOut
- 将 ChildData 映射到 ChildDataOut
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,
}
}
我想获取带有 json 标签的数据,其来源是 PascalCase 格式,并将其保存到我的数据库中。但是在进入数据库之前,我想将 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
我们需要:
- 将 Person 映射到 PersonOut
- 将 ChildData 映射到 ChildDataOut
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,
}
}