package code_test
import (
"encoding/json"
"fmt"
"go.mongodb.org/mongo-driver/bson"
"testing"
)
type Data struct {
Type int32 `bson:"Type"`
IValue IGetter `bson:"IValue"`
}
func (m *Data) UnmarshalBSON(b []byte) error {
tempData := &struct {
Type int32 `bson:"Type"`
}{}
err := bson.Unmarshal(b, tempData)
if err != nil {
fmt.Println("A", err)
}
switch tempData.Type {
case 100:
reallyData := &struct {
Type int32 `bson:"Type"`
IValue *AGetter `bson:"IValue"`
}{}
err = bson.Unmarshal(b, reallyData)
m.Type = reallyData.Type
m.IValue = reallyData.IValue
}
return nil
}
type IGetter interface {
Get() string
MarshalBSON() ([]byte, error)
}
type AGetter struct {
DataA string
}
func (m *AGetter) Get() string {
return "AGetter" + m.DataA
}
func (m *AGetter) MarshalBSON() ([]byte, error) {
t := &struct {
DataA string
}{
DataA: m.DataA,
}
return bson.Marshal(t)
//return bson.Marshal(m)
}
func TestD(t *testing.T) {
{
data := &Data{
Type: 100,
IValue: &AGetter{
DataA: "aaa",
},
}
byteData, err := bson.Marshal(data)
if err != nil {
fmt.Println(err)
}
var after = &Data{}
err = bson.Unmarshal(byteData, after)
fmt.Printf("%s
", Stringify(after))
}
}
func Stringify(o interface{}) string {
//data, err := json.MarshalIndent(o, "", " ")
data, err := json.Marshal(o)
if err != nil {
//xlog.Error(err)
return err.Error()
}
return string(data)
}
this code work success.
but i don't want to write MarshalBSON function.
just like in mgo driver: How to use interface type as a model in mgo (Go)?
It seems only UnmarshalBSON function is necessary.
But when I remove MarshalBSON in mongo-go-driver, I got an error "no encoder found for code_test.IGetter"
before find a good solution, I use this code to solve the problem...
package mongo_test_test
import (
"fmt"
mgoBson "github.com/globalsign/mgo/bson"
"go.mongodb.org/mongo-driver/bson"
"testing"
"xkit"
)
type Data struct {
Type int32 `bson:"Type"`
IValue IGetter `bson:"IValue"`
}
func (m *Data) UnmarshalBSON(b []byte) error {
tempData := &struct {
Type int32 `bson:"Type"`
}{}
err := bson.Unmarshal(b, tempData)
if err != nil {
fmt.Println("A", err)
}
switch tempData.Type {
case 100:
reallyData := &struct {
Type int32 `bson:"Type"`
IValue *AGetter `bson:"IValue"`
}{}
err = bson.Unmarshal(b, reallyData)
m.Type = reallyData.Type
m.IValue = reallyData.IValue
}
return nil
}
func (m *Data) MarshalBSON() ([]byte, error) {
return mgoBson.Marshal(m)
}
type IGetter interface {
Get() string
}
type AGetter struct {
DataA string
}
func (m *AGetter) Get() string {
return "AGetter" + m.DataA
}
func TestD(t *testing.T) {
{
data := &Data{
Type: 100,
IValue: &AGetter{
DataA: "aaa",
},
}
byteData, err := bson.Marshal(data)
if err != nil {
fmt.Println(err)
}
var after = &Data{}
err = bson.Unmarshal(byteData, after)
fmt.Printf("%s
", xkit.Stringify(after))
}
}