我正在尝试创建动态嵌套的json。我知道go是静态类型,并且有多种方法可以创建动态对象(接口),并且想知道是否有一种方法可以解决嵌套json中的依赖项映射
样本json
[
{
"display" : "Environment" ,
"field" : "test_env" ,
"value" : {
"display" : "staging",
"value" : "s"
},
"type" : "drop-down" ,
"data" : [
{
"display" : "version" ,
"field" : "test_version" ,
"value" : {
"display" : "1.1.9" ,
"value" : "1.1.9"
},
"type" : "drop-down" ,
"data" : [
{
"display" : "DataCenter" ,
"field" : "test_dc" ,
"value" : {
"display" : "washington",
"value" : "wa"
},
"type" : "drop-down" ,
"data" : [{
"display" : "Secondary" ,
"field" : "test_secondary_dc" ,
"value" : {
"display" : "miami" ,
"value" : "mi"
},
"type" : "drop-down" ,
"data" : [{
"display" : "Size" ,
"field" : "test_size" ,
"value" : {
"display" : "small" ,
"value" : "s"
}
}]
}]
}
]
}
]
},
{
"display" : "Environment" ,
"field" : "test_env" ,
"value" : {
"display" : "production",
"value" : "p"
},
"type" : "drop-down" ,
"data" : [
{
"display" : "version" ,
"field" : "test_version" ,
"value" : {
"display" : "1.1.9" ,
"value" : "1.1.9"
},
"type" : "drop-down" ,
"data" : [
{
"display" : "DataCenter" ,
"field" : "test_dc" ,
"value" : {
"display" : "miami",
"value" : "mi"
},
"type" : "drop-down" ,
"data" : [{
"display" : "Secondary" ,
"field" : "test_secondary_dc" ,
"value" : {
"display" : "washington" ,
"value" : "wa"
},
"type" : "drop-down" ,
"data" : [{
"display" : "Size" ,
"field" : "test_size" ,
"value" : {
"display" : "medium" ,
"value" : "m"
}
}]
}]
}
]
}
]
}
]
示例代码:
package main
import (
"fmt"
"reflect"
)
// struct definition ///
type RootElem struct {
RDisplay string `json:"display"`
RField string `json:"field"`
RType string `json:"type"`
RData RSlice `json:"data"`
RValue RValue `json:"value"`
}
type RValue struct {
Display string `json:"display"`
Evalue string `json:"value"`
}
type Vars struct {
Env string `json:"environment"`
Version string `json:"version"`
Zone string `json:"zone"`
PDcenter string `json:"primary_dc"`
SDcenter string `json:"secondary_dc,omitempty"`
Size string `json:"size"`
}
type RSlice []RootElem
func valueFactory(etype, evalue string) string {
switch (etype) {
case "ENVIRONMENT":
return environmentValue(evalue);
case "VERSION":
return versionValue(evalue);
case "ZONE":
return zoneValue(evalue);
case "PRIMARYDC":
return primaryValue(evalue);
case "SECONDARYDC":
return secondaryValue(evalue);
case "SIZE":
return sizeValue(evalue);
default:
return("Specifying a type we don't have.");
}
}
func sizeValue(sz string) string {
switch (sz) {
case "Small":
return "s"
case "Medium":
return "m"
case "Large" :
return "l"
default:
return "This is not a size environment value"
}
}
func environmentValue(env string) string {
switch (env) {
case "Production":
return "p"
case "staging":
return "s"
default:
return "This is not a valid environment value"
}
}
func versionValue(ver string) string {
switch (ver) {
case "1.1.9":
return "1.1.9"
default:
return "This is not a valid version value"
}
}
func zoneValue(zone string) string {
switch (zone) {
case "BLACK":
return "Black"
case "GREEN" :
return "Green"
default:
return "This is not a valid zone value"
}
}
func primaryValue(pdc string) string {
switch (pdc) {
case "washington ":
return "wa"
case "Miami" :
return "mi"
default:
return "This is not a valid primary data center value"
}
}
func secondaryValue(sdc string) string {
switch (sdc) {
case "washington":
return "wa"
case "Miami" :
return "mi"
default:
return "This is not a valid secondary data center value"
}
}
func dataGeneric(display, field, etype string) (relm RootElem) {
relm.RDisplay = display
relm.RField = field
relm.RValue.Display = ""
relm.RValue.Evalue = ""
relm.RType = etype
return relm
}
func dataEnvironment() RootElem {
display := "Environment"
field := "test_env"
etype := "dropdown"
return dataGeneric(display, field, etype)
}
func dataVersion() RootElem {
display := "Version"
field := "test_version"
etype := "dropdown"
return dataGeneric(display, field, etype)
}
func dataZone() RootElem {
display := "Zone"
field := "test_zone"
etype := "dropdown"
return dataGeneric(display, field, etype)
}
func dataPrimary() RootElem {
display := "Primary Data Center"
field := "test_dc"
etype := "dropdown"
return dataGeneric(display, field, etype)
}
func dataSecondary() RootElem {
display := "Secondary Data Center"
field := "test_secondary_dc"
etype := "dropdown"
return dataGeneric(display, field, etype)
}
func dataSize() RootElem {
display := "size"
field := "test_size"
etype := "dropdown"
return dataGeneric(display, field, etype)
}
func dataFactory(etype string) RootElem {
var rem RootElem
switch (etype) {
case "ENVIRONMENT":
return dataEnvironment()
case "VERSION":
return dataVersion()
case "ZONE":
return dataZone()
case "PRIMARYDC":
return dataPrimary()
case "SECONDARYDC":
return dataSecondary()
case "SIZE":
return dataSize()
}
return rem
}
func main() {
// sample element ///
var elment = Vars{
Env: "Production" ,
Version: "1.1.9" ,
Zone: "GREEN" ,
PDcenter: "Washington" ,
SDcenter: "Miami" ,
Size: "Small" ,
}
var Dict = []string{"ENVIRONMENT" , "VERSION" , "ZONE" , "PRIMARYDC" , "SECONDARYDC" , "SIZE" }
var newData, finalElem RootElem
for i := 0 ; i < reflect.ValueOf(elment).NumField() ; i++ {
currentElement := reflect.ValueOf(elment).Field(i).Interface()
currentElemType := Dict[i]
newData = dataFactory(currentElemType)
newData.RValue.Display = currentElement.(string)
newData.RValue.Evalue = valueFactory(currentElemType, currentElement.(string))
if finalElem.RDisplay == "" {
finalElem = newData
} else {
if len(finalElem.RData) == 0 {
finalElem.RData = append(finalElem.RData, newData)
} else {
if len(finalElem.RData[0].RData) == 0 {
finalElem.RData[0].RData = append( finalElem.RData[0].RData , newData)
} else {
if len(finalElem.RData[0].RData[0].RData) == 0 {
finalElem.RData[0].RData[0].RData = append (finalElem.RData[0].RData[0].RData , newData)
} else {
if len(finalElem.RData[0].RData[0].RData[0].RData) == 0 {
finalElem.RData[0].RData[0].RData[0].RData = append(finalElem.RData[0].RData[0].RData[0].RData, newData )
} else {
finalElem.RData[0].RData[0].RData[0].RData[0].RData = append(finalElem.RData[0].RData[0].RData[0].RData[0].RData, newData)
}
}
}
}
}
}
fmt.Println("final element" , finalElem)
}
想知道是否有一种方法可以编写用于在go中创建动态嵌套json的递归函数吗?
谢谢
答案 0 :(得分:0)
我不完全知道您要达到的目标,我运行了您的应用程序,并且您正在从平面结构中构建一棵树。为什么以及您最初的计划不清楚。
但是,应用程序不断增长的if
树始终与最后附加的RootElem相同,可以编写如下。如您所见,您的if结构现在独立于NumField()
var appendHere *RootElem
for i := 0; i < reflect.ValueOf(elment).NumField(); i++ {
[ ... stuff deleted ... ]
if finalElem.RDisplay == "" {
finalElem = newData
appendHere = &finalElem
} else {
appendHere.RData = append(appendHere.RData, newData)
appendHere = &(appendHere.RData[0])
}
}
fmt.Println("final element", finalElem)
}
将其写为评论,但答案太大,无法发表评论。