2
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\n", 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)
}

此代码工作成功。

但我不想写 MarshalBSON 函数。

就像在mgo驱动程序中一样:如何在mgo(Go)中使用接口类型作为模型?

似乎只有 UnmarshalBSON 功能是必要的。

但是当我在 mongo-go-driver 中删除 MarshalBSON 时,出现错误“找不到 code_test.IGetter 的编码器”


在找到一个好的解决方案之前,我使用这段代码来解决问题......

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\n", xkit.Stringify(after))
    }
}

4

0 回答 0