【发布时间】:2021-06-27 19:26:12
【问题描述】:
在输入时,程序接收一个 JSON。
我需要返回相同的 JSON,但使用 camelCase 键。
是否有任何有效的方法可以将 JSON 中的所有 snake_case 键转换为 Go 中的 camelCase 键?
片段代码:
package main
import (
"encoding/json"
"fmt"
"reflect"
"regexp"
"strings"
)
type CategoryList struct {
Id *string `json:"id"`
Name *string `json:"name"`
}
type Data struct {
AccessToken *string `json:"access_token"`
Category *string `json:"category"`
CategoryList []*CategoryList `json:"category_list"`
Name *string `json:"name"`
Id *string `json:"id"`
Tasks []*string `json:"tasks"`
}
type Paging struct {
Cursors *Cursors `json:"cursors"`
}
type Cursors struct {
Before *string `json:"before"`
After *string `json:"after"`
}
type Categories struct {
Data []*Data `json:"data"`
Paging *Paging `json:"paging"`
}
func main() {
jsonString := `{"data":[{"access_token":"ABCDEFGHIJKLMNOPQRSTUVWXYZ","category":"First Category","category_list":[{"id":"2301","name":"Finance App"}]},{"access_token":"ZYXWVUTSRQPONMLKJIHGFEDCBA","category":"Second Category","category_list":[{"id":"2302","name":"Medical App"}]}],"paging":{"cursors":{"before":"MTA0MjcxMzIxNjYxNTkz","after":"MTA3MTA5NDcxNDc5MTk3"}}}`
var categories map[string]interface{}
if err := json.Unmarshal([]byte(jsonString), &categories); err != nil {
panic(err)
}
modified := fromSnakeCaseToCamelCase(reflect.ValueOf(categories))
result, err := json.Marshal(modified.Interface().(map[string]interface{}))
if err != nil {
panic(err)
}
fmt.Println(string(result))
}
func fromSnakeCaseToCamelCase(value reflect.Value) reflect.Value {
switch value.Kind() {
case reflect.Array, reflect.Slice:
for i := 0; i < value.Len(); i++ {
nestedValue := value.Index(i)
fromSnakeCaseToCamelCase(nestedValue)
}
case reflect.Map:
for _, keyName := range value.MapKeys() {
nestedValue := value.MapIndex(keyName)
newKeyName := reflect.ValueOf(convertToCamelCase(keyName.Interface().(string)))
value.SetMapIndex(newKeyName, nestedValue)
oldKeyName := reflect.ValueOf(keyName.Interface().(string))
value.SetMapIndex(oldKeyName, reflect.Value{})
fromSnakeCaseToCamelCase(nestedValue)
}
default:
// pass
}
return value
}
var link = regexp.MustCompile("(^[A-Za-z]|_[A-Za-z])")
func convertToCamelCase(str string) string {
return link.ReplaceAllStringFunc(str, func(s string) string {
r := strings.NewReplacer("_", "")
return strings.ToUpper(r.Replace(s))
})
}
【问题讨论】:
-
你好,@彼得!我在 StackOverflow 上阅读了这篇文章。在这篇文章下,您的答案有两个选项。在我看来,第一个选项增加了我的代码库,因为有很多结构需要复制。如您所见,我有很多嵌套。您建议的第二个选项会将所有内容都转换为大写。
-
如果您有嵌套的结构类型,则类型转换不起作用。您可以轻松地将链接答案中的 fixKeys 函数替换为转换为驼峰大小写的函数(如答案中所述)。
标签: json go struct marshalling unmarshalling