英文:
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)。
非常感谢您的帮助
编辑:更新以显示解组部分工作,除了实例部分。
英文:
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
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 amap[string]struct{...}
. -
(Also
Id
should really beID
, 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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论