Add DefaultDocumentMap() decoder method

XMLWordPrintableJSON

    • Type: New Feature
    • Resolution: Unresolved
    • Priority: Unknown
    • 2.5.0
    • Affects Version/s: None
    • Component/s: None
    • None
    • None
    • Go Drivers
    • None
    • None
    • None
    • None
    • None
    • None

      Summary

      In v2, nested documents decode as bson.D by default, or bson.M with DefaultDocumentM(). While bson.M is defined as type M map[string]any, Go's type system treats bson.M and map[string]any as distinct types. This breaks compatibility with both internal and third-party libraries (e.g., github.com/Jeffail/gabs/v2) that expect map[string]any, user code that type-asserts nested values to map[string]any, and codebases that prohibit bson.M usage (e.g. mongosync).

      While it's fairly straight-forward to convert bson.M to map[string]any, it would be convenient for users to avoid this step as michael.mcclimon@mongodb.com correctly notes in GODRIVER-3576. The difference between 3576 and GODRIVER-3689 is that github.com/Jeffail/gabs/v2 doesn't actually take a dependency on the driver, rather it's a generic parser that simply checks for map[string]any in a type switch. Such cases have not been previously considered by the team.

      Derived from matt.dale@mongodb.com's repro, we expect the following test to pass for github.com/Jeffail/gabs/v2:

      func TestWithDefaultDocumentMap(t *testing.T) {
      	var m map[string]any
      	dec := bson.NewDecoder(bson.NewDocumentReader(bytes.NewReader(testData)))
      	dec.DefaultDocumentMap()
      
      	err := dec.Decode(&m)
      	require.NoError(t, err)
      
      	// Nested values should be map[string]any, not bson.M
      	_, ok := m["bar"].(map[string]any)
      	require.True(t, ok, "Expected m[\"bar\"] to be map[string]any, got %T", m["bar"])
      
      	// Gabs should be able to access nested values
      	blahValue := gabs.Wrap(m).Search("bar", "blah").Data()
      	require.Equal(t, "x", blahValue)
      }
      

      Acceptance Criterion

      • Add a DefaultDocumentMap() method to the bson.Decoder that causes the decoder to always unmarshal documents into the map[string]any type.
      • Extend the migration guide and bson examples to reflect this use case.

      Pitfalls

      Suggest not documenting precedence between BSONOptions and bson.Decoder methods to reduce cognitive load. It's not realistic that a user would call both DefaultDocumentMap() and DefaultDocumentM().

            Assignee:
            Unassigned
            Reporter:
            Preston Vasquez
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated: