developernaren
developernaren

Reputation: 514

Fetch plain json from mongo in go

I am trying to fetch some data from mongo in go and using gopkg.in/mgo.v2. I have a nested data in mongo.

Note: This is an old database I cannot change structure for and just want to query the data.

I have a database with fields id, name and details. and I have to get details based on id My code:

package main

import (
    "fmt"
    "gopkg.in/mgo.v2"
    "gopkg.in/mgo.v2/bson"
)

type Person struct {
    Name string
    Id string
    Details string
}


func main() {

    session, err := mgo.Dial("mongodb://localhost:27017/naren")

    c := session.DB("naren").C("people")

    result := Person{}
    err = c.Find(bson.M{"id": "12345"}).One(&result)
    if err != nil {
        fmt.Println(err)
    }

    fmt.Println("Details:", result.Details)
    fmt.Println("Name:", result.Name)
    fmt.Println("Id:", result.Id)
}

Id and Name are printing fine but result.Details prints an empty string even when there is data. I just want to print json as string or am happy with a json data.

I have also tried

...
type Person struct { 
    ...
    Details string `json:"details"`
}

But still get empty string. Thanks in advance.

Upvotes: 2

Views: 3965

Answers (2)

Manh Tai
Manh Tai

Reputation: 376

In my case, the field is an embedded document (maybe a JSON object or a JSON array). I have to set the field type to bson.RawValue:

type Person struct {
    Name string
    Id string
    Details bson.RawValue
}

and then check whether Details is an object or an array using if-else:

var d interface{}

var m bson.M
var a bson.A

e := person.Details.Unmarshal(&m)
d = m

if e != nil {
        _ = person.Details.Unmarshal(&a)
        d = a
}

After unmarshal, d will be a bson.M or bson.A.


Side note: bson.M{} objects will default be decoded to {Key: realKey, Value: realValue}, if you want {realKey: realValue} structure, unmarshal with a custom registry:

rb := bson.NewRegistryBuilder()
rb.RegisterTypeMapEntry(bsontype.EmbeddedDocument, reflect.TypeOf(bson.M{}))
reg := rb.Build()

var d interface{}

var m bson.M
var a bson.A

e := object.Data.UnmarshalWithRegistry(reg, &m)
d = m

if e != nil {
        _ = object.Data.UnmarshalWithRegistry(reg, &a)
        d = a
}

Upvotes: 0

developernaren
developernaren

Reputation: 514

I am very new to go. This seems very basic now. The value of key details was JSON

The fix was that I changed the type of details to bson.M

from

type Person struct {
    Name string
    Id string
    Details string
}

to

type Person struct {
    Name string
    Id string
    Details bson.M
}

now I can access the details like

res, err := json.Marshal(result.Details)

fmt.Println(string(res))

Thanks @putu for pointing me to the right direction.

Upvotes: 5

Related Questions