[GODRIVER-988] Document decoding to empty interface Created: 21/Apr/19 Updated: 13/Jul/23 |
|
| Status: | Backlog |
| Project: | Go Driver |
| Component/s: | Documentation |
| Affects Version/s: | None |
| Fix Version/s: | None |
| Type: | Improvement | Priority: | Major - P3 |
| Reporter: | David Golden | Assignee: | Unassigned |
| Resolution: | Unresolved | Votes: | 3 |
| Labels: | size-xsmall | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Quarter: | FY24Q3 |
| Case: | (copied to CRM) |
| Description |
|
A Reddit question about decoding SingleResult suggests that the driver will successfully decode into an empty interface variable.
It looks like the result might have been a primative.D. On one hand, this sort of makes sense because any type will satisfy the empty interface. OTOH, it's probably a user being misled by the type signature, as there's no real use for decoding to empty interface versus a concrete type or an Unmarshaler interface. I think it should either error, on the grounds that users probably made a mistake, or else we should document the behavior to indicate that decoding to empty interface defaults to primative.D. |
| Comments |
| Comment by Srikant Varadarajan [ 25/Feb/20 ] | ||||||||||||||||||||||||||||||||||||||||||
|
Hi Divjot I have a related question about Decode Lookup(filter bson.D, result interface{}) { //do bunch of mongo related stuff. s := collection.FindOne(ctx, filter) err := s.Decode(&result) logger.Printf("%+v", result) //this outputs a key value map logger.Printf("%T", result) //this outputs primitive.D } | ||||||||||||||||||||||||||||||||||||||||||
| Comment by Divjot Arora (Inactive) [ 09/Feb/20 ] | ||||||||||||||||||||||||||||||||||||||||||
|
Sorry for the confusion. We later realized that the advice given earlier in this ticket was not completely correct. We have addressed this issue in
– divjot | ||||||||||||||||||||||||||||||||||||||||||
| Comment by JAKIR SHAIKH [ 09/Feb/20 ] | ||||||||||||||||||||||||||||||||||||||||||
|
Hello @Divjot Arora I have tried a bellow solution but unfortunatly it is not working for me.
My payload is having one attribute with interface type which is getting stored correctly but while decoding it is giving ambiguous result by placing all embedded attribute to the array ({ key: "xxx", value: "xxx"} ) | ||||||||||||||||||||||||||||||||||||||||||
| Comment by Raaz Crzy [ 02/Dec/19 ] | ||||||||||||||||||||||||||||||||||||||||||
|
Another approach to solve this can be by first decoding it into bson.M type and then unmarshalling it to your struct. Yes, this is not optimal. eg:
The above snippet should be changed to:
| ||||||||||||||||||||||||||||||||||||||||||
| Comment by Pawan Sharma [ 06/Nov/19 ] | ||||||||||||||||||||||||||||||||||||||||||
|
@Divjot Arora : It worked for me, thanks a lot! | ||||||||||||||||||||||||||||||||||||||||||
| Comment by Divjot Arora (Inactive) [ 05/Nov/19 ] | ||||||||||||||||||||||||||||||||||||||||||
|
In general, we recommend using concrete types if you know what your data looks like as this will preserve type safety. If you need to unmarshal data as interface{} and have it look like JSON when it's printed out, I think the following should work:
when creating a new Client. The reason for this is that the driver defaults to unmarshalling as bson.D for interface{} where as mgo defaults to bson.M. The above code should match mgo behavior. | ||||||||||||||||||||||||||||||||||||||||||
| Comment by Pawan Sharma [ 05/Nov/19 ] | ||||||||||||||||||||||||||||||||||||||||||
|
Hi, Any updates here? | ||||||||||||||||||||||||||||||||||||||||||
| Comment by Thomas Coussot [ 13/May/19 ] | ||||||||||||||||||||||||||||||||||||||||||
|
Hi!
I have a similar problem. I need to store a complex JSON object (actually a JSON array) and so I defined a struct which look like this:
(I also tried with []interface{})
My values look like this (raw JSON before json.Decode, and also what ends up in the DB):
An important factor is that my elements don't always have a "text" field and can have other fields (children, options, label, ...). Also, elements can be nested so unstructured JSON really suits my needs.
As indicated, storing data with this struct goes smoothly. However, when retrieving data, I end up with the same kind of problem as this Issue:
The driver seems to not properly decode the document into the `interface{}` as it doesn't know which type it is. The unofficial Mongo driver (mgo) seems to handle this fine (we have used it for this several times before)
It's kinda deceiving not being able to retrieve unstructured JSON with an empty interface, just as json.Decode and mgo let us.
The only solution I found ATM is to use a different type for data, which results in a byte array in the DB.
Obviously, by doing so, data aren't readable when directly looking in the DB, which breaks interoperability and is just ugly.
I see you said that "there's no real use for decoding to empty interface", is there another way to do what I want? How can I store and retrieve a plain JSON object in a struct member?
Best regards
|