My question is very similar to this one, however instead of converting a float64
to a string
which is handled using the string tag. In my case I'm trying to convert a ObjectID
to a string using it's .Hex()
method. And, vice versa using the .FromHex()
function on the way back.
However, more generically how do I convert from type X
to type Y
& back during the Marshal
& Unmarshal
ing?
My Example:
package main
import (
"log"
"fmt"
"encoding/json"
"github.com/mongodb/mongo-go-driver/bson/objectid"
)
type Greeting struct {
Id *objectid.ObjectID `json:"id"`
Greeting string `json:"greeting,omitempty"`
}
func main() {
// Create ObjectID
id, err := objectid.FromHex("5b14dd20f6418c8443a5ffec")
if err != nil { log.Fatal(err) }
// Create Greeting
g := Greeting{&id, "Hello, World!"}
// Marshal to json
j, err := json.Marshal(g)
if err != nil { log.Fatal(err) }
// Print Json
fmt.Printf("Json: %s", string(j))
}
Output:
Json: {"id":[91,20,221,32,246,65,140,132,67,165,255,236],"greeting":"Hello, World!"}
Whereas, what I'd like is:
Json: {"id":"5b14dd20f6418c8443a5ffec","greeting":"Hello, World!"}
You should write your own (un)marshalling function in which you process your conversions/conditions and handle it as argument in calling the json (un)marshalling.
type Whatever struct {
someField int
}
func (w Whatever) MarshalJSON() ([]byte, error) {
return json.Marshal(struct{
SomeField int `json:"some_field"`
}{
SomeField: w.someField,
})
}
func (w Whatever) MarshalJSON() ([]byte, error) {
return json.Marshal(map[string]interface{}{
"some_field": w.SomeField,
})
}
You can declare a named type to objectid.ObjectId
that would implement the json.Marshaler
interface to override the standard marshaling and output the hex string instead:
type Id objectid.ObjectId
func (id Id) MarshalJSON() ([]byte, error) {
return json.Marshal(objectid.ObjectId(id).Hex())
}
And use it instead of objectid.ObjectId
in your structs:
type Greeting struct {
Id Id
Greeting string
}
Now, as you marshal a Greeting
, the json package would marshal the Greeting
field as expected, but the since the Id
field implements json.Marshaler
, it would be marshaled by Id.MarshalJSON
which would output id.Hex()
.
You can do the same for unmarshaling by implementing the json.Unmarshaler
interface for Id
.