[英]Converting a complex struct to a simple json
背景
我有一个结构,我通过 API 作为 json 传递给用户。 这行得通。
我现在正在尝试发送与 object 相同的结构,我的 UI 可以轻松转换为 csv 并允许用户下载。
我有在 UI 上工作的代码,可以将简单对象转换为 CSV。 所以我可以发送一个 object 值只是整数或字符串没问题。 但是,我的结构的值是对象和 arrays。 因此,我正在尝试找到一种方法将复杂的 json object 转换为更简单的方法。 更简单的 object 应该只具有没有引号的值(如 int)或只有一组外部引号(如字符串)。
问题
如何将 golang 结构转换为具有“简单”值(字符串、布尔值、int 但不是数组或带有更多引号的 object)的 json?
例子
例如,此代码将用户转换为 json,格式如下:
{
"Name":"Frank",
"Friends":[{"Age":10,"Name":"Joe"}, {"Age":12,"Name":"John"}],
"FavSnacks":["apple","orange"]
}
,但我想要格式
{
"Name":"Frank",
"Friends":"[{'Age':10,'Name':'Joe'},{'Age':12,'Name':'John'}]",
"FavSnacks":"['apple','orange']"
}
或者
{
"Name":"Frank",
"Friends":"[{Age:10, Name:Joe},{Age:12,Name:John}]",
"FavSnacks":"[apple, orange]"
}
这是我的代码
package main
import (
"fmt"
"encoding/json"
)
type User struct {
Name string
Friends []Friend
FavSnacks []string
}
type Friend struct {
Age int
Name string
}
func main() {
user := &User{Name: "Frank", FavSnacks: []string{"apple","orange"}, Friends: []Friend{{Age: 10, Name: "Joe"},{Age: 12, Name: "John"}} }
b, err := json.Marshal(user)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(b))
}
笔记
使用要编组的值构建 map。 使用反射 API 遍历结构中的字段并收集 map 中的值。 如果字段的值是切片或结构,则将该字段编码为 JSON 并在 map 中使用该值。 返回编码为 JSON 的 map。
func marshalFlat(value interface{}) ([]byte, error) {
v := reflect.Indirect(reflect.ValueOf(value))
t := v.Type()
// Collect all fields in this map.
m := make(map[string]interface{})
for i := 0; i < t.NumField(); i++ {
sf := t.Field(i)
if sf.PkgPath != "" {
// skip unexported
continue
}
f := reflect.Indirect(v.Field(i))
switch f.Kind() {
case reflect.Slice, reflect.Struct:
// Encode slices and structs as JSON and use
// that JSON as the value of the field.
p, err := json.Marshal(f.Interface())
if err != nil {
return nil, err
}
m[sf.Name] = string(p)
default:
// User other types as is.
m[sf.Name] = f.Interface()
}
}
return json.Marshal(m)
}
只需实现 Marshaler 接口:)
package main
import (
"encoding/json"
"fmt"
"strings"
)
type User struct {
Name string `json:"name"`
Friends Friends `json:"friends"`
FavSnacks FavSnacks `json:"fav_snacks"`
}
type Friend struct {
Age int `json:"age"`
Name string `json:"name"`
}
type Friends []Friend
func (f *Friends) MarshalJSON() ([]byte, error) {
type FriendsAux []Friend
friendsAux := FriendsAux(*f)
marshal, err := json.Marshal(friendsAux)
if err != nil {
return []byte{}, nil
}
escapedMarshal := strings.ReplaceAll(string(marshal), `"`, `'`)
jsonToString := fmt.Sprintf(`"%s"`, escapedMarshal)
return []byte(jsonToString), nil
}
type FavSnacks []string
func (f *FavSnacks) MarshalJSON() ([]byte, error) {
type FavSnacksAux []string
favSnacksAux := FavSnacksAux(*f)
marshal, err := json.Marshal(favSnacksAux)
if err != nil {
return []byte{}, nil
}
escapedMarshal := strings.ReplaceAll(string(marshal), `"`, `'`)
jsonToString := fmt.Sprintf(`"%s"`, escapedMarshal)
return []byte(jsonToString), nil
}
func main() {
user := &User{Name: "Frank", FavSnacks: []string{"apple","orange"}, Friends: []Friend{{Age: 10, Name: "Joe"},{Age: 12, Name: "John"}} }
b, err := json.Marshal(user)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(b))
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.