After using InsertOne
to create a new document, when I return the result I'm getting an array of numbers rather than an ObjectID
. In the DB, the id is generating fine.
type User struct {
ID string
Email string
Username string
Password string
}
var db = ...
// UserStore creates user
func UserStore(c echo.Context) (err error) {
coll := db.Collection("users")
u := new(User)
if err = c.Bind(u); err != nil {
return c.JSON(http.StatusInternalServerError, err)
}
result, err := coll.InsertOne(
context.Background(),
bson.NewDocument(
bson.EC.String("email", u.Email),
bson.EC.String("username", u.Username),
bson.EC.String("password", u.Password),
),
)
if err != nil {
return c.JSON(http.StatusInternalServerError, err)
}
return c.JSON(http.StatusCreated, result)
}
This returns something like InsertedID: [90, 217, 85, 109, 184, 249, 162, 204, 249, 103, 214, 121]
instead of a normal ObjectID
. How can I return the actual ObjectID
from the newly inserted document?
A successful Collection.InsertOne()
will return a result of type mongo.InsertOneResult
, which is a struct wrapping the ID of the newly inserted document:
type InsertOneResult struct {
// The identifier that was inserted.
InsertedID interface{}
}
The official MongoDB Go driver uses the primitive.ObjectID
type to represent MongoDB ObjectIds. This type is a simple byte array:
type ObjectID [12]byte
To access this type you need to import the primitive package.
import "go.mongodb.org/mongo-driver/bson/primitive"
InsertOneResult.InsertedID
will hold a dynamic type of primitive.ObjectID
. The primitive.ObjectID
type does not define a custom JSON marshaling method (does not implement json.Marshaler
), which means when the result is converted to JSON, the default marshaling rules will be used, which for a byte array (not slice) is what you see: the decimal representation of the bytes of the ObjectID.
You should not convert a value of type InsertOneResult
to JSON, as it (or rather primitive.ObjectID
itself) is not "JSON-friendly" (at least not in the current version).
Instead create / wrap your own type where you define how you want the result to look like in JSON, for example:
if oid, ok := result.InsertedID.(primitive.ObjectID); ok {
return c.JSON(http.StatusCreated, map[string]interface{}{
"id": oid.String(),
})
} else {
// Not objectid.ObjectID, do what you want
}
The above code would result in a JSON response like this:
{"id":"ObjectID(\"5ad9a913478c26d220afb681\")"}
Or if you just want the hex representation:
if oid, ok := result.InsertedID.(primitive.ObjectID); ok {
return c.JSON(http.StatusCreated, map[string]interface{}{
"id": oid.Hex(),
})
}
Which would be:
{"id":"5ad9a913478c26d220afb681"}