所以你有一个带有components 键的对象,它是一个组件切片。这些组件中的每一个都可以有许多键。首先要做的是评估一个组件可以拥有的所有可能的字段,并使用这些字段定义一个类型:
type Validation struct {
Required bool `json:"required"`
}
type Value struct {
Label string `json:"label"`
Value string `json:"value"`
Shortcut string `json:"shortcut"`
}
type Data struct {
Components []Data `json:"components,omitempty"`
Collapsable bool `json:"collapsable"`
Input bool `json:"input"`
Key string `json:"key"`
TableView bool `json:"tableView"`
Type string `json:"type"`
Value string `json:"value"`
UseLocaleSettings bool `json:"useLocaleSettings"`
Values []Value `json:"values,omitempty"`
Validate *Validation `json:"validate,omitempty"`
}
现在您只需将输入解组为 Data 类型:
data := Data{}
if err := json.Unmarshal([]byte(input), &data); err != nil {
// handle error
fmt.Printf("Oops, something went wrong: %+v", err)
return
}
此时,我们已经将所有数据都放在了一个结构体中,因此我们可以开始将其全部打印出来。我们注意到的第一件事是Data 基本上包含Data 类型的切片。将其全部打印出来的递归函数是有意义的:
func PrintComponents(data []Data) {
for _, c := range data {
if len(c.Components) > 0 {
PrintComponents(c.Components) // recursive
continue // skip value of this component, remove this line if needed
}
val := c.Value // assign string value
if len(c.Values) > 0 {
// this component has a slice of values, not a single value
vals, err := json.MarshalIndent(c.Values, "", " ") // marshal with indent of 4 spaces, no prefix
if err != nil {
fmt.Printf("Oops, looks like we couldn't format something: %+v\n", err)
return // handle this
}
val = string(vals) // marshalled values as string
}
fmt.Printf("Key: %s Value: %s\n", c.Key, val) // print output
}
}
你可以稍微改变这个函数,为每一级递归传递一个缩进参数,这样你就可以打印出缩进块中的组件:
func PrintComponents(data []Data, indent string) {
for _, c := range data {
if len(c.Components) > 0 {
// print the key for this block of components
fmt.Printf("Component block: %s\n", c.Key)
PrintComponents(data, indent + " ") // current indent + 4 spaces
continue // we're done with this component
}
val := c.Value
if len(c.Values) > 0 {
vals, _ := json.MarshalIndent(c.Values, indent, " ") // pass in indent level here, and DON'T ignore the error, that's just for brevity
val = string(vals)
}
fmt.Printf("%sKey: %s Value: %s\n", indent, c.Key, val) // pass in indent
}
}
综合起来,我们得到this:
func main() {
data := Data{}
if err := json.Unmarshal(input, &data); err != nil {
fmt.Println(err.Error())
return
}
fmt.Println("Printing with simple recursive function")
// print all components, these could be nested, so let's use a recursive function
PrintComponents(data.Components)
fmt.Println("\n\nPrinting with indented recursion:")
PrintComponentsIndent(data.Components, "") // start with indent of 0
}
func PrintComponents(data []Data) {
for _, c := range data {
if len(c.Components) > 0 {
PrintComponents(c.Components) // recursive
continue // skip value of this component, remove this line if needed
}
val := c.Value // assign string value
if len(c.Values) > 0 {
// this component has a slice of values, not a single value
vals, err := json.MarshalIndent(c.Values, "", " ") // marshal with indent of 4 spaces, no prefix
if err != nil {
fmt.Printf("Oops, looks like we couldn't format something: %+v\n", err)
return // handle this
}
val = string(vals) // marshalled values as string
}
fmt.Printf("Key: %s Value: %s\n", c.Key, val) // print output
}
}
func PrintComponentsIndent(data []Data, indent string) {
for _, c := range data {
if len(c.Components) > 0 {
fmt.Printf("%sComponent block: %s\n", indent, c.Key)
PrintComponentsIndent(c.Components, indent + " ")
continue
}
val := c.Value
if len(c.Values) > 0 {
// this component has a slice of values, not a single value
vals, _ := json.MarshalIndent(c.Values, indent, " ")
val = string(vals) // marshalled values as string
}
fmt.Printf("%sKey: %s Value: %s\n", indent, c.Key, val) // print output
}
}
哪些输出:
Printing with simple recursive function
Key: custname Value: Abraham
Key: type Value: [
{
"label": "Sole",
"value": "sole",
"shortcut": ""
},
{
"label": "Bata",
"value": "Bata",
"shortcut": ""
}
]
Key: registeredField Value: reg 111
Key: dirc Value: abraham
Key: gst Value: textfield
Key: pan Value: AAAAA0000
Printing with indented recursion:
Component block: d1
Key: custname Value: Abraham
Key: type Value: [
{
"label": "Sole",
"value": "sole",
"shortcut": ""
},
{
"label": "Bata",
"value": "Bata",
"shortcut": ""
}
]
Key: registeredField Value: reg 111
Key: dirc Value: abraham
Key: gst Value: textfield
Key: pan Value: AAAAA0000
您想要的输出不包括值切片的方括号。嗯,这是一件很容易摆脱的事情。方括号始终是字符串的第一个和最后一个字符,json.Marshal 返回一个字节切片 ([]byte)。删除第一个和最后一个字符很简单:
val = string(vals[1:len(vals)-2])
获取json.Marshal返回的字节切片的一个子切片,从偏移量1开始(剪切偏移量0,即[),并保留所有内容直到倒数第二个字符(偏移量len(vals)-2) .对于缩进的示例,这将给您留下一个空白行,其中包含未知数量的空格(缩进)。您可以使用 strings 包修剪字符串的右侧:
// remove square brackets, trim trailing new-line and spaces
val = strings.TrimRight(string(vals[1:len(vals)-2]), "\n ")