解码JSON保留所有密钥

时间:2016-10-05 07:13:44

标签: json go

我有这种类型的JSON结构

{
  "iptables" : false,
  "dns" : ["8.8.8.8","8.8.4.4"]
}

在解开JSON对象之上的过程中,我需要保留密钥,例如{ "<server>": { "<guest>": { "<service>": { "<part>": { "num": "<number>", "type": "<type>", "timestamp": "2016-02-01T12:53:12Z" } } } } } server等。我想到了struct下面但是我无法在JSON对象上解组,因为在解组时键会丢失。

guest

有没有办法将JSON对象上面解组成struct保持密钥完整。

编辑:
type Section struct { Bytes int Files int Timestamp time.Time } type Report struct { Server string Guest string Service string Part string Details Section } 内的文字正在发生变化。这就是为什么我需要在松散之后保留它以便我可以进一步研究它。

3 个答案:

答案 0 :(得分: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>"`
    }

答案 1 :(得分: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}}

答案 2 :(得分:1)

我写过a library可以让这更容易使用。可以针对您的JSON格式解组Reports

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