(Golang) InvalidBSON when using custom MarshalBSON()

Viewed 48

I am currently migrating some of my Python Services to GoLang, where I encountered some problems with the integration with the existing database.

When it comes to saving, the formatting of the date string is different, and I am not planning to change the format of my database entries.

So I decided to implement a time type, with custom (Un)MarshalBSON() methods, to keep pythons time formatting. However when saving it, I get the following error:

2022/09/10 20:57:29 (InvalidBSON) Unrecognized BSON type 45 in element with field name 'created_at.09-10 20:57:27.798545' in object with _id: ObjectId('631cde192c2aad6a49bc52af')

I don't know how the field created_at.09-10 20:57:27.798545 came up.

Thank you for advance four your advice, here is my source code:

main.go:

package main

import (
    "context"
    "example/customdate/user"
    "fmt"
    "log"
)

func main() {
    ctx := context.Background()
    repo := user.NewRepository(ctx)
    u1 := user.NewUser("Max")
    u1, err := repo.Add(ctx, u1)
    if err != nil {
        log.Fatalln(err)
    }
    fmt.Println(u1)
}

user/repository.go:

package user

import (
    "context"
    "log"

    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/options"
)

type Repository interface {
    Get(ctx context.Context) ([]User, error)

    Add(ctx context.Context, user *User) (*User, error)
}

type repository struct {
    client *mongo.Client
}

func NewRepository(ctx context.Context) repository {
    c, err := mongo.NewClient(options.Client().ApplyURI("mongodb://127.0.0.1:27017/"))
    if err != nil {
        log.Fatalln(err)
    }
    
    err = c.Connect(ctx)
    if err != nil {
        log.Fatal(err)
    }

    return repository{
        client: c,
    }
}

func (r *repository) Get(ctx context.Context) ([]User, error) {
    result, err := r.client.Database("db").Collection("user").Find(ctx, map[string]interface{}{})
    if err != nil {
        return nil, err
    }

    var users []User
    if err = result.All(ctx, &users); err != nil {
        return nil, err
    }

    return users, nil
}

func (r *repository) Add(ctx context.Context, user *User) (*User, error) {
    result, err := r.client.Database("db").Collection("user").InsertOne(ctx, user)
    if err != nil {
        return nil, err
    }

    user.ID = result.InsertedID

    return user, nil
}

user/dto.go:

package user

import "time"

type CustomTime struct {
    time.Time
}
func (t *CustomTime) MarshalBSON() ([]byte, error) {
    str := t.Format("2006-01-02 15:04:05.999999") 
    return []byte(str), nil 
}

func (t *CustomTime) UnmarshalBSON(raw []byte) error {
    parsed, err := time.Parse("2006-01-02 15:04:05.999999", string(raw))
    if err != nil {
        return err
    }
    t = &CustomTime{parsed}
    return nil
}

func Now() CustomTime {
    return CustomTime{time.Now()}
}

type User struct {
    ID interface{}
    Name string `bson:"name"`
    CreatedAt CustomTime `bson:"created_at"`
}

func NewUser(name string) *User {
    return &User{
        Name: name,
        CreatedAt: Now(),
    }
}
0 Answers
Related