动态变化的 json 解析 求指导

oslet · · 1697 次点击
非常感谢指导, 采用此方式,有利于缓存到 redis
#3
更多评论
```go package main import ( "encoding/json" "fmt" "reflect" ) type Systree map[string]*Sys type Sys struct { WebArr []Detail1 `json:"web"` AppArr []Detail1 `json:"app"` DBArr []Detail1 `json:"db"` } func (self *Sys) UnmarshalJSON(b []byte) error { fmt.Println("Sys Unmarshal") m := map[string]interface{}{} if err := json.Unmarshal(b, &m); err != nil { //fmt.Println("1 err:", err) return err } t := reflect.TypeOf(*self) val := reflect.ValueOf(self) val = reflect.Indirect(val) n := t.NumField() for i := 0; i < n; i++ { sf := t.Field(i) tag := sf.Tag.Get("json") name := sf.Name v := m[tag] if _v, ok := v.(map[string]interface{}); ok { v = []interface{}{_v} } //fmt.Printf("tag: %v, v:%#v\n", sf.Tag, v) fv := val.FieldByName(name) //fmt.Printf("fv:%v, name:%v\n", fv, name) fb, err := json.Marshal(v) if err != nil { //fmt.Println("2 err:", err) return err } err = json.Unmarshal(fb, fv.Addr().Interface()) if err != nil { //fmt.Println("3 err:", err) return err } //fmt.Printf("fb: %v\n", string(fb)) //fmt.Printf("fv:%v, name:%v\n", fv, name) } return nil } type Detail1 struct { Name string `json:"name"` Ip string `json:"ip"` Cpu string `json:"cpu"` Mem string `json:"mem"` Disk string `json:"disk"` } func main() { body := ` { "sys1": { "web": [ { "name": "web-01-www-01", "ip": "10.1.69.101", "cpu": "2", "mem": "4", "disk": "40" }, { "name": "web-01-www-02", "ip": "10.1.69.102", "cpu": "2", "mem": "4", "disk": "40" } ], "app": { "name": "app-01-www-01", "ip": "10.2.69.101", "cpu": "2", "mem": "4", "disk": "40" }, "db": { "name": "db-01-www-01", "ip": "10.2.69.101", "cpu": "2", "mem": "4", "disk": "40" } }, "sys2": { "web": { "name": "web-02-www-01", "ip": "10.3.69.101", "cpu": "2", "mem": "4", "disk": "40" } } } ` r := make(Systree) err := json.Unmarshal([]byte(body), &r) if err != nil { fmt.Printf("err: %v\n", err) } for k, v := range r { fmt.Printf("k: %#v\n", k) fmt.Printf("v: %#v\n", v) } fmt.Println(len(r)) } ```
#1
package main import ( "encoding/json" "fmt" "reflect" ) type Systree map[string]*Sys type Sys struct { WebArr []Detail1 `json:"web"` AppArr []Detail1 `json:"app"` DBArr []Detail1 `json:"db"` } func (self *Sys) UnmarshalJSON(b []byte) error { fmt.Println("Sys Unmarshal") m := map[string]interface{}{} if err := json.Unmarshal(b, &m); err != nil { //fmt.Println("1 err:", err) return err } t := reflect.TypeOf(*self) val := reflect.ValueOf(self) val = reflect.Indirect(val) n := t.NumField() for i := 0; i < n; i++ { sf := t.Field(i) tag := sf.Tag.Get("json") name := sf.Name v := m[tag] if _v, ok := v.(map[string]interface{}); ok { v = []interface{}{_v} } //fmt.Printf("tag: %v, v:%#v\n", sf.Tag, v) fv := val.FieldByName(name) //fmt.Printf("fv:%v, name:%v\n", fv, name) fb, err := json.Marshal(v) if err != nil { //fmt.Println("2 err:", err) return err } err = json.Unmarshal(fb, fv.Addr().Interface()) if err != nil { //fmt.Println("3 err:", err) return err } //fmt.Printf("fb: %v\n", string(fb)) //fmt.Printf("fv:%v, name:%v\n", fv, name) } return nil } type Detail1 struct { Name string `json:"name"` Ip string `json:"ip"` Cpu string `json:"cpu"` Mem string `json:"mem"` Disk string `json:"disk"` } func main() { body := ` { "sys1": { "web": [ { "name": "web-01-www-01", "ip": "10.1.69.101", "cpu": "2", "mem": "4", "disk": "40" }, { "name": "web-01-www-02", "ip": "10.1.69.102", "cpu": "2", "mem": "4", "disk": "40" } ], "app": { "name": "app-01-www-01", "ip": "10.2.69.101", "cpu": "2", "mem": "4", "disk": "40" }, "db": { "name": "db-01-www-01", "ip": "10.2.69.101", "cpu": "2", "mem": "4", "disk": "40" } }, "sys2": { "web": { "name": "web-02-www-01", "ip": "10.3.69.101", "cpu": "2", "mem": "4", "disk": "40" } } } ` r := make(Systree) err := json.Unmarshal([]byte(body), &r) if err != nil { fmt.Printf("err: %v\n", err) } for k, v := range r { fmt.Printf("k: %#v\n", k) fmt.Printf("v: %#v\n", v) } fmt.Println(len(r)) }
#2