解码JSON并保留所有键

I have JSON structure of this type

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

During unmarshaling above JSON object I need to preserve keys e.g. server,guest etc. I thought of below struct but I am unable to unmarshal above JSON object as keys are lost during unmarshalling.

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

Is there any way to unmarshal above JSON object into struct keeping keys intact.

Edit:
Text inside <server> is changing. That is why I need to preserve it after unmarshlling so that I can work further on it.

1- Try it on 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
}

output:

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

2- Converting to Report struct, try it on 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
}

output:

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

For above JSON this structure will work fine.

    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>"`
    }

I've written a library that could make this easier to work with. The Reports can be unmarshaled against your JSON format:

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
}

You can now do this:

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)
}