dsndm82062 2019-01-02 16:40
浏览 30
已采纳

go中具有依赖条件的动态数据结构(嵌套json)

I'm trying to create dynamically nested json in go. i understand that go is static type and there are various ways to create dynamic objects(interfaces) and wondering if there is a way to tackle my dependency mapping in nested json

sample 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"
             }
              }]
            }]
        }
      ]
    }
  ]
}
]

sample code :

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)

}

wondering if there is a way to write a recursive function for creating dynamic nested json in go?

thanks

  • 写回答

1条回答 默认 最新

  • dongluan0020 2019-01-02 18:20
    关注

    I don't know exactly what you are trying to achive, I ran your application, and you are building a tree from the flat structure. Why and what your original plan was is not clear.

    Yet, your application's ever growing if tree is always doing the same with the last appended RootElem and can be written as follows. As you can see, your if structure is now independent from 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)
    }
    

    Would have written this as comment, but the answer is too large for comments.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?