Golang的json.Unmarshal不按预期工作。

huangapple go评论78阅读模式
英文:

Golang json.Unmarshal is not working as expected

问题

我正在尝试从vCenter REST API的JSON响应中解组。当响应体简单地打印出来时,它看起来像下面的输出:

{"value":[{"memory_size_MiB":16384,"vm":"vm-10236","name":"Normal_Windows_192.168.1.10","power_state":"POWERED_OFF","cpu_count":8},{"memory_size_MiB":8192,"vm":"vm-10238","name":"Normal_Windows_192.168.1.11","power_state":"POWERED_OFF","cpu_count":4}]}

我已经导出了结构体和结构体字段,但是像memory_size_MiBpower_statecpu_count这样的字段没有被解组。当打印结构体时,它看起来像下面这样:

{Value:[{Mem:0 Vm:vm-10236 Name:Normal_Windows_192.168.1.10 Powerstat: Cpu:0} {Mem:0 Vm:vm-10238 Name:Normal_Windows_192.168.1.11 Powerstat: Cpu:0} {Mem:0 Vm:vm-10582 Name:Normal_Windows_192.168.1.12 Powerstat: Cpu:0}]}%

以下是我的main.go代码:

package main

import (
    ...
)

type SessionData struct {
    VmwareApiSessionId string `json:"value"`
}

type Vm struct {
    Mem       int    `json:"memory_size_MiB"`
    Vm        string `json:"vm"`
    Name      string `json:"name"`
    Powerstat string `json:"power_state"`
    Cpu       int    `json:"cpu_count"`
}

type ColVmList struct {
    Value []Vm `json:"value"`
}

func getVmList(sessid string, cli *http.Client) ColVmList {
    vms := ColVmList{}
    req, err := http.NewRequest("GET", "https://sandbox.vmware.local/rest/vcenter/vm", nil)
    req.Header.Add("vmware-api-session-id", sessid)
    resp, err := cli.Do(req)
    if err != nil {
        log.Fatal("Error %s", err)
    }
    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)
    fmt.Println(string(body))
    err = json.Unmarshal([]byte(body), &vms)
    if err != nil {
        log.Fatal("error %s", err)
    }
    return vms
}

func main() {
    //authpart
    loginurl = "https://sandbox.vmware.local/rest/com/vmware/cis/session"
    //login...
    err = json.Unmarshal([]byte(string(body)), &sessVal)
    if err != nil {
        log.Fatal(err)
    }
    var allvmlist ColVmList
    allvmlist = getVmList(sessVal.VmwareApiSessionId, &cli)
    fmt.Printf("%v", allvmlist)
}

以上是你要翻译的内容。

英文:

Im trying to unmarshal json response from vcenter rest api. when the response body is simply printed it looks like the o/p below

{"value":[{"memory_size_MiB":16384,"vm":"vm-10236","name":"Normal_Windows_192.168.1.10","power_state":"POWERED_OFF","cpu_count":8},{"memory_size_MiB":8192,"vm":"vm-10238","name":"Normal_Windows_192.168.1.11","power_state":"POWERED_OFF","cpu_count":4}]}

i have exported both struct and struct fields however the fields like memory_size_MiB, power_state,cpu_count is not being unmarshalled. when the struct is printed it looks like below:-

{Value:[{Mem:0 Vm:vm-10236 Name:Normal_Windows_192.168.1.10 Powerstat: Cpu:0} {Mem:0 Vm:vm-10238 Name:Normal_Windows_192.168.1.11 Powerstat: Cpu:0} {Mem:0 Vm:vm-10582 Name:Normal_Windows_192.168.1.12 Powerstat: Cpu:0}]}% 

Below is my main.go

    package main
import (
...
)
type SessionData struct {
VmwareApiSessionId string `json:"value"`
}
//{"memory_size_MiB":16384,"vm":"vm-10236","name":"Normal_Windows_192.168.19.100","power_state":"POWERED_OFF","cpu_count":8}
type Vm struct {
Mem int `json: "memory_size_MiB"`
Vm string `json: "vm"`
Name string `json: "name"`
Powerstat string `json: "power_state"`
Cpu int `json: "cpu_count"`
}
//{Value:[{Mem:0 Vm:vm-10236 Name:Normal_Windows_192.168.1.10 Powerstat: Cpu:0} {Mem:0 Vm:vm-10238 Name:Normal_Windows_192.168.1.11 Powerstat: Cpu:0} {Mem:0 Vm:vm-10582 Name:Normal_Windows_192.168.1.12 Powerstat: Cpu:0}]}
type ColVmList struct {
Value []Vm `json: "value"`
}
func getVmList(sessid string,cli *http.Client) ColVmList {
vms := ColVmList{}
req,err:=http.NewRequest("GET","https://sandbox.vmware.local/rest/vcenter/vm",nil)
req.Header.Add("vmware-api-session-id",sessid)
resp,err := cli.Do(req)
if err != nil {
log.Fatal("Error %s", err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
err = json.Unmarshal([]byte(body),&vms)
if err != nil {
log.Fatal("error %s", err)
}
return vms
}
func main(){
//authpart
loginurl = "https://sandbox.vmware.local/rest/com/vmware/cis/session"
//login...
err = json.Unmarshal([]byte(string(body)),&sessVal)
if  err != nil{
log.Fatal(err)
}
var allvmlist ColVmList
allvmlist = getVmList(sessVal.VmwareApiSessionId,&cli)
fmt.Printf("%v",allvmlist)
}

答案1

得分: 2

你的结构标签格式不正确。在结构标签中,删除json:和字符串"..."之间的空格。即应该是json:"..."而不是json: "..."

一些字段即使结构标签格式不正确,也能正确解组的原因是字段的名称与JSON属性名称匹配。

func main() {
	data := []byte(`{"memory_size_MiB":16384}`)

	var obj1 struct {
		Mem int `json: "memory_size_MiB"`
	}
	if err := json.Unmarshal(data, &obj1); err != nil {
		panic(err)
	}
	fmt.Println(obj1)

	var obj2 struct {
		Mem int `json:"memory_size_MiB"`
	}
	if err := json.Unmarshal(data, &obj2); err != nil {
		panic(err)
	}
	fmt.Println(obj2)
}

https://go.dev/play/p/gUR5ed2n0D1

英文:

Your struct tags are not well formed. Remove the space between json: and the string "..." in the struct tags. i.e. it MUST be json:"..." not json: "...".

And the reason some fields are correctly unmarshaled even with not well-formed struct tags is because the fields' names match the json property names.

func main() {
	data := []byte(`{"memory_size_MiB":16384}`)

	var obj1 struct {
		Mem int `json: "memory_size_MiB"`
	}
	if err := json.Unmarshal(data, &obj1); err != nil {
		panic(err)
	}
	fmt.Println(obj1)

	var obj2 struct {
		Mem int `json:"memory_size_MiB"`
	}
	if err := json.Unmarshal(data, &obj2); err != nil {
		panic(err)
	}
	fmt.Println(obj2)
}

https://go.dev/play/p/gUR5ed2n0D1

huangapple
  • 本文由 发表于 2022年2月27日 17:53:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/71283727.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定