在Golang中进行JSON的反序列化(Unmarshalling)

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

Umarshalling this JSON in Golang

问题

我正在自学如何在Golang中使用JSON包。对于很多事情来说,它似乎很简单,但是我在解析从我的3D打印机检索到的一些JSON数据时遇到了问题。JSON的格式如下:

{
"tasks": [
{
"class": "Task",
"id": "5fee231a",
"instances": {
"28253266": {
"class": "StateInstance",
"id": "28253266",
"progress": 1,
"stateType": "Y-EdgeAvoiding"
},
"1d774b49": {
"class": "StateInstance",
"id": "1d774b49",
"progress": 1,
"stateType": "X-Calibration"
}
},
"stateType": "StartingUp"
}
]
}

基本上,打印机有一个正在执行的任务(在上面的示例中,任务的ID是5fee231a),并且在其中有子任务(例如任务28253266)。

如果我使用以下代码:

var vals interface{}
err = json.Unmarshal([]byte(myJSON), &vals)

if err != nil {
    fmt.Println("Error:", err)
}

spew.Dump(&vals)

(使用github.com/davecgh/go-spew来转储变量),那么我会得到一些输出(注意:这不是完整的输出,为了简洁起见进行了裁剪):

(*map[string]interface {})(0xc0820068e0)((len=1) {
(string) (len=5) "tasks": ([]interface {}) (len=1 cap=1) {
(map[string]interface {}) (len=4) {
(string) (len=5) "class": (string) (len=4) "Task",
(string) (len=2) "id": (string) (len=8) "5fee231a",
(string) (len=9) "instances": (map[string]interface {}) (len=13) {
(string) (len=8) "bd65d028": (map[string]interface {}) (len=4) {
(string) (len=5) "class": (string) (len=13) "StateInstance",
(string) (len=2) "id": (string) (len=8) "bd65d028",
(string) (len=8) "progress": (float64) 1,
(string) (len=9) "stateType": (string) (len=17) "CenteringPosition"
},
(string) (len=8) "d1e225e7": (map[string]interface {}) (len=4) {
(string) (len=2) "id": (string) (len=8) "d1e225e7",
(string) (len=8) "progress": (float64) 1,
(string) (len=9) "stateType": (string) (len=10) "TargetCold",
(string) (len=5) "class": (string) (len=13) "StateInstance"
},

这很好,但是我想能够获取给定实例的状态(例如询问X-Calibration的进度,返回1)。因此,我创建了一些结构体:

type Message struct {
Tasks []struct {
Class string
Id string
Instances []struct {
Something []struct {
Class string
Id string
StateType string
}
}
}
}

Tasks可以被解组,但是实例无法解组:

====================== Error: json: cannot unmarshal object into Go value of type []struct { Something struct { Class string; Id string; StateType string } }
(*buccaneer.Message)(0xc082002c40)({
Tasks: ([]struct { Class string; Id string; Instances []struct { Something struct { Class string; Id string; StateType string } } }) (len=1 cap=4) {
(struct { Class string; Id string; Instances []struct { Something struct { Class string; Id string; StateType string } } }) {
Class: (string) (len=4) "Task",
Id: (string) (len=8) "5fee231a",
Instances: ([]struct { Something struct { Class string; Id string; StateType string } })
}
}
})

请注意其中的something结构体。我不知道该结构体应该命名为什么,因为实例具有唯一的名称(即每个“子任务”具有不同的ID)。

非常感谢您的帮助 在Golang中进行JSON的反序列化(Unmarshalling)

编辑:更新以显示解组部分工作,除了实例部分。

英文:

I'm teaching myself how to use the JSON package in Golang. It seems straightforward for a lot of things, but I'm having troubles parsing some JSON data I retrieved from my 3D printer. The JSON looks like this:

{
    "tasks": [
        {
            "class": "Task",
            "id": "5fee231a",
            "instances": {
                "28253266": {
                    "class": "StateInstance",
                    "id": "28253266",
                    "progress": 1,
                    "stateType": "Y-EdgeAvoiding"
                },
                "1d774b49": {
                    "class": "StateInstance",
                    "id": "1d774b49",
                    "progress": 1,
                    "stateType": "X-Calibration"
                },
            },
            "stateType": "StartingUp"
        }
    ]
}

(NB: There's a few more "instances", but I didn't include them for brevity, but they all follow this pattern, but with a different stateType)

Basically, the printer has a task that it is doing (in the example above, the task has an ID of 5fee231a) and within it, sub-tasks (e.g. Task 28253266).

If I use this code:

	var vals interface{}
	err = json.Unmarshal([]byte(myJSON), &vals)

	if err != nil {
		fmt.Println("Error:", err)
	}

	spew.Dump(&vals)

(using github.com/davecgh/go-spew to dump the variable), then I get some output (NB: This isn't the whole output, it's snipped for brevity :)):

(*map[string]interface {})(0xc0820068e0)((len=1) {
 (string) (len=5) "tasks": ([]interface {}) (len=1 cap=1) {
  (map[string]interface {}) (len=4) {
   (string) (len=5) "class": (string) (len=4) "Task",
   (string) (len=2) "id": (string) (len=8) "5fee231a",
   (string) (len=9) "instances": (map[string]interface {}) (len=13) {
    (string) (len=8) "bd65d028": (map[string]interface {}) (len=4) {
     (string) (len=5) "class": (string) (len=13) "StateInstance",
     (string) (len=2) "id": (string) (len=8) "bd65d028",
     (string) (len=8) "progress": (float64) 1,
     (string) (len=9) "stateType": (string) (len=17) "CenteringPosition"
    },
    (string) (len=8) "d1e225e7": (map[string]interface {}) (len=4) {
     (string) (len=2) "id": (string) (len=8) "d1e225e7",
     (string) (len=8) "progress": (float64) 1,
     (string) (len=9) "stateType": (string) (len=10) "TargetCold",
     (string) (len=5) "class": (string) (len=13) "StateInstance"
    },

This is nice, but I'd like to be be able to grab the status of a given instance (e.g. ask for the progress of X-Calibration, get 1 in return). So I created some structs:

type Message struct {
	Tasks []struct {
		Class     string
		Id        string
		Instances []struct {
			Something []struct {
				Class     string
				Id        string
				StateType string
			}
		}
	}
}

Tasks gets unmarshalled, but none of the instances:

====================== Error: json: cannot unmarshal object into Go value of type []struct { Something struct { Class string; Id string; StateType string } }
(*buccaneer.Message)(0xc082002c40)({
 Tasks: ([]struct { Class string; Id string; Instances []struct { Something struct { Class string; Id string; StateType string } } }) (len=1 cap=4) {
  (struct { Class string; Id string; Instances []struct { Something struct { Class string; Id string; StateType string } } }) {
   Class: (string) (len=4) "Task",
   Id: (string) (len=8) "5fee231a",
   Instances: ([]struct { Something struct { Class string; Id string; StateType string } }) <nil>
  }
 }
})

And note the something struct in there. I don't know what to name that struct, as the instances have unique names (i.e. each "sub-task" has a different ID)

Any help is much appreciated 在Golang中进行JSON的反序列化(Unmarshalling)

EDIT: Updated to show that unmarshalling is partially working, except for the Instances

答案1

得分: 3

  • Instances 需要是一个 map,因为它是一个对象。

  • 你不需要在其中使用 Something,因为它已经是一个 map[string]struct{...}

  • (另外 Id 应该是 ID,但这只是一个风格上的小问题。)

类型定义如下:

type Message struct {
    Tasks []struct {
        Class     string
        ID        string
        Instances map[string]struct {
            Class     string
            ID        string
            StateType string
        }
    }
}

Playground: http://play.golang.org/p/r-wjaEiwP0.

英文:
  • Instances needs to be a map, because it's an object.

  • You don't need Something inside of it, since it's already a map[string]struct{...}.

  • (Also Id should really be ID, but that's a stylistic nitpick.)

The type:

type Message struct {
    Tasks []struct {
        Class     string
        ID        string
        Instances map[string]struct {
            Class     string
            ID        string
            StateType string
        }
    }
}

Playground: http://play.golang.org/p/r-wjaEiwP0.

答案2

得分: 0

除了Ainar-G发布的答案之外,我发现了一个网站(http://json2struct.mervine.net/),它可以根据你粘贴的任何JSON生成结构体。

当我粘贴了我的打印机的JSON时,生成的代码非常混乱,远不如上面提供的答案那样简洁和完整,但如果你有一些简单的JSON需要快速转换为结构体,这个网站可能对你有用。

英文:

In addition to the answer posted by Ainar-G, I discovered this website which generates structs for you, based on whatever JSON you paste in.

When I pasted in the JSON from my printer, the resulting code was a total mess, not nearly as compact and complete as the answers provided above, but if you have some simple JSON that you'd like to quickly convert to a struct, this might be of use to you.

huangapple
  • 本文由 发表于 2015年7月23日 21:37:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/31589040.html
匿名

发表评论

匿名网友

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

确定