2016-10-05 17 views
0

予有这种类型解码JSON保持所有键

{ 
    "<server>": { 
     "<guest>": { 
      "<service>": { 
       "<part>": { 
        "num": "<number>", 
        "type": "<type>", 
        "timestamp": "2016-02-01T12:53:12Z" 
       } 
      } 
     } 
    } 
} 

的JSON结构在上述JSON对象解编我需要例如保存键server,guest等。我想到了下面的结构,但我无法解开上面的JSON对象,因为键在解组过程中丢失。

type Section struct { 
    Bytes  int  
    Files  int  
    Timestamp time.Time 
} 
type Report struct { 
    Server string 
    Guest string 
    Service string 
    Part string 
    Details Section 
} 

有没有什么办法解开上面的JSON对象到结构保持键完好无损。

编辑:
<server>中的文字正在改变。这就是为什么我需要在不加修饰的情况下保存它,以便我可以继续努力。

+0

里面' “” 文本'const或不?例如:''或只是''? – 2016-10-05 07:24:58

+0

@Amd 中的文字正在改变。这就是为什么我需要保持它unmarshlling后,我可以进一步工作。 – shivams

+0

是否可以稍微改变你的JSON格式?例如'{ “服务器”: “Server12”, “客人”: “Guest2”, “服务”: “服务2”, “部分”: “第2部分”, “详细信息”:{ “字节”:1, “文件”:2 ,“Timestamp”:“2016-10-05T07:21:22.9887031Z”}}'或者它超出了你的控制范围? – 2016-10-05 07:30:17

回答

1

1-尝试在The Go Playground

package main 

import (
    "encoding/json" 
    "fmt" 
    "time" 
) 

func main() { 
    s := `{ 
    "<server1>": { 
     "<guest2>": { 
      "<service3>": { 
       "<part4>": { 
        "num": 12, 
        "type": 14, 
        "timestamp": "2016-02-01T12:53:12Z" 
       } 
      } 
     } 
    } 
}` 

    var data map[string]map[string]map[string]map[string]Section 
    err := json.Unmarshal([]byte(s), &data) 
    if err != nil { 
     fmt.Println(err) 
    } 

    fmt.Println(data) 
} 

type Section struct { 
    Bytes  int  `json:"num"` 
    Files  int  `json:"type"` 
    Timestamp time.Time `json:"timestamp"` 
} 
type Report struct { 
    Server string 
    Guest string 
    Service string 
    Part string 
    Details Section 
} 

输出:

map[<server1>:map[<guest2>:map[<service3>:map[<part4>:{12 14 2016-02-01 12:53:12 +0000 UTC}]]]] 

2-转换为Report struct,尝试在The Go Playground

package main 

import (
    "encoding/json" 
    "fmt" 
    "time" 
) 

func main() { 
    s := `{ 
    "<server1>": { 
     "<guest2>": { 
      "<service3>": { 
       "<part4>": { 
        "num": 12, 
        "type": 14, 
        "timestamp": "2016-02-01T12:53:12Z" 
       } 
      } 
     } 
    } 
}` 

    var data map[string]map[string]map[string]map[string]Section 
    err := json.Unmarshal([]byte(s), &data) 
    if err != nil { 
     fmt.Println(err) 
    } 
    r := Report{} 
    for k, v := range data { 
     r.Server = k 
     for k2, v2 := range v { 
      r.Guest = k2 
      for k3, v3 := range v2 { 
       r.Service = k3 
       for k4, v4 := range v3 { 
        r.Part = k4 
        r.Details = v4 
       } 
      } 
     } 
    } 
    fmt.Println(r) 
} 

type Section struct { 
    Bytes  int  `json:"num"` 
    Files  int  `json:"type"` 
    Timestamp time.Time `json:"timestamp"` 
} 
type Report struct { 
    Server string 
    Guest string 
    Service string 
    Part string 
    Details Section 
} 

输出:

{<server1> <guest2> <service3> <part4> {12 14 2016-02-01 12:53:12 +0000 UTC}} 
1

对于上面的JSON,这个结构可以正常工作。

type Report struct { 
     Server struct { 
      Guest struct { 
       Service struct { 
        Part struct { 
         Num string `json:"num"` 
         Type string `json:"type"` 
         Timestamp time.Time `json:"timestamp"` 
        } `json:"<part>"` 
       } `json:"<service>"` 
      } `json:"<guest>"` 
     } `json:"<server>"` 
    } 
+0

上面的结构给我输出{{{{{0001-01-01 00:00:00 +0000 UTC}}}}}'为'{“server”的json结构:{“guest”:{“{服务“:{”part“:{ ”num“:”1024“, ”type“:”10“, ”timestamp“:”2016-02-21T12:53:12Z“ }}}}} – shivams

+1

上面的结构也不会保留键,即我不能访问服务器,结构中的客人名字。 – shivams

1

我写a library,可以使这个更容易使用。该Reports可解组对你的JSON格式:

package main 

import (
    "time" 

    "github.com/go-restit/lzjson" 
) 

type Section struct { 
    Bytes  int  `json:"num"` 
    Files  int  `json:"type"` 
    Timestamp time.Time `json:"timestamp"` 
} 

type Report struct { 
    Server string 
    Guest string 
    Service string 
    Part string 
    Details Section 
} 

type Reports []Report 

func (reports *Reports) UnmarshalJSON(content []byte) (err error) { 

    root := lzjson.NewNode() 
    if err = json.Unmarshal(content, &root); err != nil { 
     return 
    } 

    // reset the slice of reports 
    *reports = make([]Report, 0, 10) 

    for _, serverName := range root.GetKeys() { 
     server := root.Get(serverName) 
     if err = server.Error(); err != nil { 
      return 
     } 
     for _, guestName := range server.GetKeys() { 
      guest := server.Get(guestName) 
      if err = guest.Error(); err != nil { 
       return 
      } 
      for _, serviceName := range guest.GetKeys() { 
       service := guest.Get(serviceName) 
       if err = service.Error(); err != nil { 
        return 
       } 
       for _, partName := range service.GetKeys() { 
        part := service.Get(partName) 
        if err = part.Error(); err != nil { 
         return 
        } 
        var report Report 
        timestamp, _ := time.Parse("2006-01-02T15:04:05Z", part.Get("timestamp").String()) 
        report.Server = serverName 
        report.Guest = guestName 
        report.Service = serviceName 
        report.Part = partName 
        report.Details = Section{ 
         Bytes:  part.Get("num").Int(), 
         Files:  part.Get("type").Int(), 
         Timestamp: timestamp, 
        } 
        *reports = append(*reports, report) 
       } 
      } 
     } 
    } 
    return 
} 

现在你可以这样做:

package main 

import (
    "encoding/json" 
    "log" 
) 

func main() { 
    raw := ` 
    { 
     "<server 1>": { 
      "<guest>": { 
       "<service>": { 
        "<part>": { 
         "num": "<number>", 
         "type": "<type>", 
         "timestamp": "2016-02-01T12:53:12Z" 
        } 
       } 
      } 
     }, 
     "<server 2>": { 
      "<guest>": { 
       "<service>": { 
        "<part>": { 
         "num": "<number>", 
         "type": "<type>", 
         "timestamp": "2016-02-01T12:53:12Z" 
        } 
       } 
      } 
     } 
    }` 
    var reports Reports 
    err := json.Unmarshal([]byte(raw), &reports) 
    if err != nil { 
     log.Fatalf("error reading reports: %s", err.Error()) 
    } 
    log.Printf("Reports: %#v", reports) 
}