What's the proper way to convert a json.RawMessage to a struct?

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

What's the proper way to convert a json.RawMessage to a struct?

问题

我有这个struct

type SyncInfo struct {
    Target string
}

现在我从ElasticSearch查询一些json数据。Source的类型是json.RawMessage
我想要的只是将source映射到我创建的SyncInfo,我为此创建了变量mySyncInfo

我已经找到了如何做到这一点...但感觉有点奇怪。我首先调用MarshalJSON()来获取一个[]byte,然后将其传递给json.Unmarshal(),它接受一个[]byte和指向我的结构体的指针。

这样做可以正常工作,但感觉好像多了一步。我是否漏掉了什么,或者这是从json.RawMessagestruct的预期方式?

var mySyncInfo SyncInfo

jsonStr, _ := out.Hits.Hits[0].Source.MarshalJSON()
json.Unmarshal(jsonStr, &mySyncInfo)

fmt.Print(mySyncInfo.Target)

以上是翻译好的内容,请确认是否正确。

英文:

I have this struct

type SyncInfo struct {
    Target string
}

Now I query some json data from ElasticSearch. Source is of type json.RawMessage.
All I want is to map source to my SyncInfo which I created the variable mySyncInfo for.

I even figured out how to do that...but it seems weird. I first call MarshalJSON() to get a []byte and then feed that to json.Unmarshal() which takes an []byte and a pointer to my struct.

This works fine but it feels as if I'm doing an extra hop. Am I missing something or is that the intended way to get from a json.RawMessage to a struct?

var mySyncInfo SyncInfo

jsonStr, _ := out.Hits.Hits[0].Source.MarshalJSON()
json.Unmarshal(jsonStr, &mySyncInfo)

fmt.Print(mySyncInfo.Target)

答案1

得分: 40

如上所述,json.RawMessage 的底层类型是 []byte,因此您可以将 json.RawMessage 作为数据参数传递给 json.Unmarshal

然而,您的问题在于您有一个指针(*json.RawMessage)而不是一个值。您只需要对其进行解引用:

err := json.Unmarshal(*out.Hits.Hits[0].Source, &mySyncInfo)

工作示例:

package main

import (
	"encoding/json"
	"fmt"
)

type SyncInfo struct {
	Target string
}

func main() {
	data := []byte(`{"target": "localhost"}`)
	Source := (*json.RawMessage)(&data)

	var mySyncInfo SyncInfo
	// 注意解引用的星号 *
	err := json.Unmarshal(*Source, &mySyncInfo)
	if err != nil {
		panic(err)
	}

	fmt.Printf("%+v\n", mySyncInfo)
}

输出:

{Target:localhost}

Playground: http://play.golang.org/p/J8R3Qrjrzx

英文:

As said, the underlying type of json.RawMessage is []byte, so you can use a json.RawMessage as the data parameter to json.Unmarshal.

However, your problem is that you have a pointer (*json.RawMessage) and not a value. All you have to do is to dereference it:

err := json.Unmarshal(*out.Hits.Hits[0].Source, &mySyncInfo)

Working example:

package main

import (
	"encoding/json"
	"fmt"
)

type SyncInfo struct {
	Target string
}

func main() {
	data := []byte(`{"target": "localhost"}`)
	Source := (*json.RawMessage)(&data)

	var mySyncInfo SyncInfo
	// Notice the dereferencing asterisk *
	err := json.Unmarshal(*Source, &mySyncInfo)
	if err != nil {
		panic(err)
	}

	fmt.Printf("%+v\n", mySyncInfo)
}

Output:

{Target:localhost}

Playground: http://play.golang.org/p/J8R3Qrjrzx

答案2

得分: 4

json.RawMessage实际上只是一个字节切片。你可以直接将它传递给json.Unmarshal,像这样:

json.Unmarshal(out.Hits.Hits[0].Source, &mySyncInfo)

另外,虽然与此无关,但json.Unmarshal可能会返回一个错误,你需要处理它:

err := json.Unmarshal(*out.Hits.Hits[0].Source, &mySyncInfo)
if err != nil {
    // 处理错误
}
英文:

json.RawMessage is really just a slice of bytes. You should be able to feed it directly into json.Unmarshal directly, like so:

json.Unmarshal(out.Hits.Hits[0].Source, &mySyncInfo)

Also, somewhat unrelated, but json.Unmarshal can return an error and you want to handle that.

err := json.Unmarshal(*out.Hits.Hits[0].Source, &mySyncInfo)
if err != nil {
    // Handle
}

huangapple
  • 本文由 发表于 2014年4月24日 05:24:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/23255456.html
匿名

发表评论

匿名网友

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

确定