Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

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) 
like image 685
Christoph Avatar asked Apr 23 '14 21:04

Christoph


People also ask

What is JSON RawMessage?

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.

How does JSON Unmarshal work?

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.

How do I decode JSON in Golang?

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.


2 Answers

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

like image 166
ANisus Avatar answered Sep 20 '22 05:09

ANisus


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 } 
like image 29
Zach Latta Avatar answered Sep 22 '22 05:09

Zach Latta