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)
RawMessage is a raw encoded JSON value. It implements Marshaler and Unmarshaler and can be used to delay JSON decoding or precompute a JSON encoding. Example (Marshal) This example uses RawMessage to use a precomputed JSON during marshal.
Unmarshal() function takes some encoded JSON data and a pointer to a value where the encoded JSON should be written, and returns an error if something goes wrong.
To parse JSON, we use the Unmarshal() function in package encoding/json to unpack or decode the data from JSON to a struct. Unmarshal parses the JSON-encoded data and stores the result in the value pointed to by v. Note: If v is nil or not a pointer, Unmarshal returns an InvalidUnmarshalError.
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
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 }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With