Adam D
Adam D

Reputation: 2197

Unable to Decode the ObjectId SubValue from MongoDB results in Golang

I am using the MongoDb Go Driver and I am unable to get the ObjectId subvalue from the JSON decoded in my structs.

Note: I am using a different library/API than this question, so please don't mark this as duplicate.

import (
    "net/http"
    "github.com/go-chi/chi"
    "encoding/json"
    "time"
    "context"
    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/options"
    "go.mongodb.org/mongo-driver/bson"
    "go.mongodb.org/mongo-driver/bson/primitive"
    "fmt"
)

I have a type of struct like this for processing the results

type Contact struct {
    Id  struct {
        ObjId   string  `json:"$oid"`
    } `json:"_id"`
    Name    string `json:"name"`
    Email   string `json:"email"`
    Health  struct {
        Weight  int `json:"weight"`
        Height  int `json:"height"`
    } `json:"health"`    
}

And then I go to retrieve the contacts like this:

var contacts []Contact
ctx, _ := context.WithTimeout(context.Background(), 30*time.Second)
cursor, err := collection.Find(ctx, bson.M{})
if err != nil {
    panic(err)
}
defer cursor.Close(ctx)
for cursor.Next(ctx) {
    var contact Contact
    fmt.Println(cursor)
    cursor.Decode(&contact)
    contacts = append(contacts, contact)
}
if err := cursor.Err(); err != nil {
    panic(err)
}
// I want to do more with the contacts, but .Id is empty :-(
fmt.Println(contacts)

The subfields for "health" appear exactly as they should, but for some reason the subfield from the "_id" part of the results is nowhere to be found. Can anyone help me with this??

The JSON response from the database comes out like this, and for some reason I am able to get the subfields for the health field, but not the _id field. Why not?

Raw JSON response of DB

[{
    "_id": { 
        "$obj": "5c601648ae25e40e2631c3ef" 
    }, 
    "name": "Bob Smith", 
    "email": "[email protected]", 
    "health": { 
        "height": 192, 
        "weight": 85 
    }
}]

fmt.Println's output of the decoded contacts array:

[{{} Bob Smith [email protected] {192 85}}]

Upvotes: 6

Views: 7875

Answers (2)

Adam D
Adam D

Reputation: 2197

Thanks to this excellent tutorial and this anwser I was able to find the answer.

I needed to set the ID in my struct as a primitive.ObjectID, and made sure I had imported "go.mongodb.org/mongo-driver/bson/primitive"

type Contact struct {
    ID      primitive.ObjectID  `json:"_id" bson:"_id"
    Name    string `json:"name" bson:"name"`
    Email   string `json:"email" bson:"email"`
    Health  struct {
        Weight  int `json:"weight" bson:"weight"`
        Height  int `json:"height" bson:"height"`
    } `json:"health" bson:"health"`    
}

For those looking to use the official MongoDB Go driver, see this tutorial below provides very good explanation and examples of how to do all the CRUD operations necessary for a basic REST api etc.

Using the official MongoDB Go driver

Upvotes: 17

pete911
pete911

Reputation: 809

looks to me that you are missing 'bson' tags. You have correctly tagged json, but not bson. The rest of the fields is fine, because they default to correct bson tags, but '_id' default to just 'id'. Try to add

json:"_id" bson:"_id"

Upvotes: 4

Related Questions