I want to get data with json tag whose source has PascalCase format and save it to my database. But before going into the database, I want to change the PascalCase format to snake_case format.
My question seems to be the opposite of this question (Golang Unmarshal an JSON response, then marshal with Struct field names). But instead of having PascalCase, I want to have snake_case in the name field
Here is the sample code that i wrote:
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)
}
The result that I want is like
{
"first_name": "Grisha",
"last_name": "Jeager",
"children": [
{
"child_name": "Zeke",
"age": 2,
"fav_color": "blue"
},
{
"child_name": "Eren",
"age": 3,
"fav_color": "red"
}
]
}
but the result is still having PascalCase in the nested field:
{
"first_name": "Grisha",
"last_name": "Jeager",
"children": [
{
"ChildName": "Zeke",
"Age": 2,
"FavColor": "blue"
},
{
"ChildName": "Eren",
"Age": 3,
"FavColor": "red"
}
]
}
I was wondering how to convert field name for the nested structure from unmarshal JSON.
Converting one struct to another works only if their their underlying types (ignoring tags) are identical. If the underlying types are not identical you cannot do the conversion.
Take for example the structs
S1
andS2
, in the following snippet their underlying types are identical and you can convert one to the other:However, in the next snippet their underlying types are NOT identical and therefore you cannot convert one to the other:
For more details read the spec on conversions here: https://go.dev/ref/spec#Conversions
So to convert between two struct whose underlying types are NOT identical you have to manually do the conversion field by field. However, in the case of JSON marshaling, you can make this a bit nicer by implementing the
json.Marshaler
interface and have the individual instances "convert themselves".https://go.dev/play/p/UGJY5p490Gs