Golang使用未知密钥解析JSON

I'm trying to unmarshal json with dynamic field keys to the struct That json returned from storcli utility for linux. One part of the code work well, but if json data contains many structs I can't unmarshal it. I think that is because DriveDetailedInformation struct do not have all json tags. Can anybody help me?

package main

import (
    "fmt"
    "encoding/json"
)

type jsonStruct struct {
    Controllers []struct {
        CommandStatus struct {
            Controller  int    `json:"Controller"`
            Status      string `json:"Status"`
            Description string `json:"Description"`
        } `json:"Command Status"`
        ResponseData map[string]*json.RawMessage `json:"Response Data"`
    } `json:"Controllers"`
}

type DriveStruct struct {
    EIDSlt string `json:"EID:Slt"`
    DID    int    `json:"DID"`
    State  string `json:"State"`
    DG     int    `json:"DG"`
    Size   string `json:"Size"`
    Intf   string `json:"Intf"`
    Med    string `json:"Med"`
    SED    string `json:"SED"`
    PI     string `json:"PI"`
    SeSz   string `json:"SeSz"`
    Model  string `json:"Model"`
    Sp     string `json:"Sp"`
}

type DriveDetailedInformation struct {
    DriveState            map[string]DriveStateStruct
    DriveDeviceAttributes map[string]DriveDeviceAttributesStruct
    DrivePoliciesSettings map[string]DrivePoliciesSettingsStruct
    InquiryData           string `json:"Inquiry Data"`
}

type DriveStateStruct struct {
    ShieldCounter            int    `json:"Shield Counter"`
    MediaErrorCount          int    `json:"Media Error Count"`
    OtherErrorCount          int    `json:"Other Error Count"`
    BBMErrorCount            int    `json:"BBM Error Count"`
    DriveTemperature         string `json:"Drive Temperature"`
    PredictiveFailureCount   int    `json:"Predictive Failure Count"`
    SMARTAlertFlaggedByDrive string `json:"S.M.A.R.T alert flagged by drive"`
}

type DriveDeviceAttributesStruct struct {
    SN               string `json:"SN"`
    ManufacturerID   string `json:"Manufacturer Id"`
    ModelNumber      string `json:"Model Number"`
    NANDVendor       string `json:"NAND Vendor"`
    WWN              string `json:"WWN"`
    FirmwareRevision string `json:"Firmware Revision"`
    RawSize          string `json:"Raw size"`
    CoercedSize      string `json:"Coerced size"`
    NonCoercedSize   string `json:"Non Coerced size"`
    DeviceSpeed      string `json:"Device Speed"`
    LinkSpeed        string `json:"Link Speed"`
    NCQSetting       string `json:"NCQ setting"`
    WriteCache       string `json:"Write cache"`
    SectorSize       string `json:"Sector Size"`
    ConnectorName    string `json:"Connector Name"`
}

type DrivePoliciesSettingsStruct struct {
    DrivePosition                            string `json:"Drive position"`
    EnclosurePosition                        int    `json:"Enclosure position"`
    ConnectedPortNumber                      string `json:"Connected Port Number"`
    SequenceNumber                           int    `json:"Sequence Number"`
    CommissionedSpare                        string `json:"Commissioned Spare"`
    EmergencySpare                           string `json:"Emergency Spare"`
    LastPredictiveFailureEventSequenceNumber int    `json:"Last Predictive Failure Event Sequence Number"`
    SuccessfulDiagnosticsCompletionOn        string `json:"Successful diagnostics completion on"`
    SEDCapable                               string `json:"SED Capable"`
    SEDEnabled                               string `json:"SED Enabled"`
    Secured                                  string `json:"Secured"`
    Locked                                   string `json:"Locked"`
    NeedsEKMAttention                        string `json:"Needs EKM Attention"`
    PIEligible                               string `json:"PI Eligible"`
    Certified                                string `json:"Certified"`
    WidePortCapable                          string `json:"Wide Port Capable"`
    PortInformation                          []struct {
        Port       int    `json:"Port"`
        Status     string `json:"Status"`
        Linkspeed  string `json:"Linkspeed"`
        SASAddress string `json:"SAS address"`
    } `json:"Port Information"`
}

var jsonData = `
{
   "Controllers":[
      {
         "Command Status":{
            "Controller":0,
            "Status":"Success",
            "Description":"Show Drive Information Succeeded."
         },
         "Response Data":{
            "Drive /c0/e31/s0":[
               {
                  "EID:Slt":"31:0",
                  "DID":19,
                  "State":"Onln",
                  "DG":0,
                  "Size":"9.094 TB",
                  "Intf":"SATA",
                  "Med":"HDD",
                  "SED":"N",
                  "PI":"N",
                  "SeSz":"512B",
                  "Model":"ST10000DM0004-1ZC101",
                  "Sp":"U"
               }
            ],
            "Drive /c0/e31/s0 - Detailed Information":{
               "Drive /c0/e31/s0 State":{
                  "Shield Counter":0,
                  "Media Error Count":0,
                  "Other Error Count":0,
                  "BBM Error Count":0,
                  "Drive Temperature":" 25C (77.00 F)",
                  "Predictive Failure Count":0,
                  "S.M.A.R.T alert flagged by drive":"No"
               },
               "Drive /c0/e31/s0 Device attributes":{
                  "SN":"            ZA23V0DH",
                  "Manufacturer Id":"ATA     ",
                  "Model Number":"ST10000DM0004-1ZC101",
                  "NAND Vendor":"NA",
                  "WWN":"5000c500a5ad06b6",
                  "Firmware Revision":"DN01    ",
                  "Raw size":"9.095 TB [0x48c400000 Sectors]",
                  "Coerced size":"9.094 TB [0x48c300000 Sectors]",
                  "Non Coerced size":"9.094 TB [0x48c300000 Sectors]",
                  "Device Speed":"6.0Gb/s",
                  "Link Speed":"6.0Gb/s",
                  "NCQ setting":"N/A",
                  "Write cache":"N/A",
                  "Sector Size":"512B",
                  "Connector Name":""
               },
               "Drive /c0/e31/s0 Policies/Settings":{
                  "Drive position":"DriveGroup:0, Span:0, Row:0",
                  "Enclosure position":0,
                  "Connected Port Number":"0(path0) ",
                  "Sequence Number":2,
                  "Commissioned Spare":"No",
                  "Emergency Spare":"No",
                  "Last Predictive Failure Event Sequence Number":0,
                  "Successful diagnostics completion on":"N/A",
                  "SED Capable":"No",
                  "SED Enabled":"No",
                  "Secured":"No",
                  "Locked":"No",
                  "Needs EKM Attention":"No",
                  "PI Eligible":"No",
                  "Certified":"No",
                  "Wide Port Capable":"No",
                  "Port Information":[
                     {
                        "Port":0,
                        "Status":"Active",
                        "Linkspeed":"6.0Gb/s",
                        "SAS address":"0x5003048001927c6c"
                     }
                  ]
               },
               "Inquiry Data":""
            },
            "Drive /c0/e31/s1":[
               {
                  "EID:Slt":"31:1",
                  "DID":20,
                  "State":"Onln",
                  "DG":0,
                  "Size":"9.094 TB",
                  "Intf":"SATA",
                  "Med":"HDD",
                  "SED":"N",
                  "PI":"N",
                  "SeSz":"512B",
                  "Model":"ST10000DM0004-1ZC101",
                  "Sp":"U"
               }
            ],
            "Drive /c0/e31/s1 - Detailed Information":{
               "Drive /c0/e31/s1 State":{
                  "Shield Counter":0,
                  "Media Error Count":0,
                  "Other Error Count":0,
                  "BBM Error Count":0,
                  "Drive Temperature":" 25C (77.00 F)",
                  "Predictive Failure Count":0,
                  "S.M.A.R.T alert flagged by drive":"No"
               },
               "Drive /c0/e31/s1 Device attributes":{
                  "SN":"            ZA23MCVS",
                  "Manufacturer Id":"ATA     ",
                  "Model Number":"ST10000DM0004-1ZC101",
                  "NAND Vendor":"NA",
                  "WWN":"5000c500a5acc582",
                  "Firmware Revision":"DN01    ",
                  "Raw size":"9.095 TB [0x48c400000 Sectors]",
                  "Coerced size":"9.094 TB [0x48c300000 Sectors]",
                  "Non Coerced size":"9.094 TB [0x48c300000 Sectors]",
                  "Device Speed":"6.0Gb/s",
                  "Link Speed":"6.0Gb/s",
                  "NCQ setting":"N/A",
                  "Write cache":"N/A",
                  "Sector Size":"512B",
                  "Connector Name":""
               },
               "Drive /c0/e31/s1 Policies/Settings":{
                  "Drive position":"DriveGroup:0, Span:0, Row:1",
                  "Enclosure position":0,
                  "Connected Port Number":"0(path0) ",
                  "Sequence Number":2,
                  "Commissioned Spare":"No",
                  "Emergency Spare":"No",
                  "Last Predictive Failure Event Sequence Number":0,
                  "Successful diagnostics completion on":"N/A",
                  "SED Capable":"No",
                  "SED Enabled":"No",
                  "Secured":"No",
                  "Locked":"No",
                  "Needs EKM Attention":"No",
                  "PI Eligible":"No",
                  "Certified":"No",
                  "Wide Port Capable":"No",
                  "Port Information":[
                     {
                        "Port":0,
                        "Status":"Active",
                        "Linkspeed":"6.0Gb/s",
                        "SAS address":"0x5003048001927c6d"
                     }
                  ]
               },
               "Inquiry Data":""
            }
         }
      }
   ]
}
`

func main() {
    var f jsonStruct
    err := json.Unmarshal([]byte(jsonData), &f)
    if err != nil {
        fmt.Println("Error parsing JSON: ", err)
    }

    for _, controller := range f.Controllers {
        for k, v := range controller.ResponseData {

            ///THAT IS WORK
            var ds []DriveStruct
            if err := json.Unmarshal(*v, &ds); err == nil {
                fmt.Println(k, ds)

            }

            ///THAT IS NOT WORK WHY?
            var dds DriveDetailedInformation
            if err := json.Unmarshal(*v, &dds); err == nil {
                fmt.Println(k, dds)
            }
        }
    }
}
duanmi1900
duanmi1900 解组不会返回任何错误,但是DriveDetailedInformation结构中的所有映射都是空的。
大约 2 年之前 回复
doudou130216
doudou130216 您是什么意思“无法解组”?为什么不?您面临的问题是什么?
大约 2 年之前 回复

1个回答

Because your key value is not correct. Below is the code I modified.

type DriveDetailedInformation struct {
DriveState            DriveStateStruct `json:"Drive /c0/e31/s0 State"`
DriveDeviceAttributes DriveDeviceAttributesStruct `json:"Drive /c0/e31/s0 Device attributes"`
DrivePoliciesSettings DrivePoliciesSettingsStruct `json:"Drive /c0/e31/s0 Policies/Settings"`
InquiryData           string `json:"Inquiry Data"`
}

type DriveDetailedInformation1 struct {
    DriveState            DriveStateStruct `json:"Drive /c0/e31/s1 State"`
    DriveDeviceAttributes DriveDeviceAttributesStruct `json:"Drive /c0/e31/s1 Device attributes"`
    DrivePoliciesSettings DrivePoliciesSettingsStruct `json:"Drive /c0/e31/s1 Policies/Settings"`
    InquiryData           string `json:"Inquiry Data"`
}
func main() {
    var f jsonStruct
    err := json.Unmarshal([]byte(jsonData), &f)
    if err != nil {
        fmt.Println("Error parsing JSON: ", err)
    }

    for _, controller := range f.Controllers {
        for k, v := range controller.ResponseData {
            switch k {
            case "Drive /c0/e31/s0","Drive /c0/e31/s1":
                var ds []DriveStruct
                if err := json.Unmarshal(*v, &ds); err == nil {
                    fmt.Println(k, ds)
                }
            case "Drive /c0/e31/s1 - Detailed Information":
                var dds1 DriveDetailedInformation1
                if err := json.Unmarshal(*v, &dds1); err == nil {
                    fmt.Println(k, dds1)
                }
            case "Drive /c0/e31/s0 - Detailed Information":
                var dds DriveDetailedInformation
                if err := json.Unmarshal(*v, &dds); err == nil {
                    fmt.Println(k, dds)
                }
            }
        }
    }
}

I think Response Data can be parsed in a structure.

donglei_0507
donglei_0507 我不能比json :(
大约 2 年之前 回复
drot98385
drot98385 因此,您只需要嵌套几层地图[string] * json.RawMessage,我认为这非常乏味,因此您最好修改JSON并添加名称字段。例如:{“ Drive”:[{ “名称”:“驱动器/ c0 / e31 / s0”,...}],“驱动器详细信息”:[{“ driveName”:“驱动器/ c0 / e31 / s0”,“名称”:“驱动器/ c0 / e31 / s0-详细信息”,...}]}
大约 2 年之前 回复
du7999
du7999 json:“驱动器/ c0 / e31 / s1设备属性”-是动态密钥,我无法对其进行硬编码。
大约 2 年之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐