Skip to content

Commit c898612

Browse files
author
iwysiu
authored
GODRIVER-1433 add mgoRegistryRespectNilValues (#275)
1 parent afd796b commit c898612

File tree

2 files changed

+73
-48
lines changed

2 files changed

+73
-48
lines changed

bson/mgocompat/bson_test.go

Lines changed: 40 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1710,58 +1710,55 @@ func TestMarshalNotRespectNil(t *testing.T) {
17101710
assert.NotNil(t, testStruct2.Map, "expected non-nil map")
17111711
}
17121712

1713-
// func TestMarshalRespectNil(t *testing.T) {
1714-
// type T struct {
1715-
// Slice []int
1716-
// SlicePtr *[]int
1717-
// Ptr *int
1718-
// Map map[string]interface{}
1719-
// MapPtr *map[string]interface{}
1720-
// }
1721-
1722-
// bson.SetRespectNilValues(true)
1723-
// defer bson.SetRespectNilValues(false)
1713+
func TestMarshalRespectNil(t *testing.T) {
1714+
type T struct {
1715+
Slice []int
1716+
SlicePtr *[]int
1717+
Ptr *int
1718+
Map map[string]interface{}
1719+
MapPtr *map[string]interface{}
1720+
}
17241721

1725-
// testStruct1 := T{}
1722+
testStruct1 := T{}
17261723

1727-
// assert.Nil(t, testStruct1.Slice, "expected nil slice, got: %v", testStruct1.Slice)
1728-
// assert.Nil(t, testStruct1.SlicePtr, "expected nil slice ptr, got: %v", testStruct1.SlicePtr)
1729-
// assert.Nil(t, testStruct1.Map, "expected nil map, got: %v", testStruct1.Map)
1730-
// assert.Nil(t, testStruct1.MapPtr, "expected nil map ptr, got: %v", testStruct1.MapPtr)
1731-
// assert.Nil(t, testStruct1.Ptr, "expected nil ptr, got: %v", testStruct1.Ptr)
1724+
assert.Nil(t, testStruct1.Slice, "expected nil slice, got: %v", testStruct1.Slice)
1725+
assert.Nil(t, testStruct1.SlicePtr, "expected nil slice ptr, got: %v", testStruct1.SlicePtr)
1726+
assert.Nil(t, testStruct1.Map, "expected nil map, got: %v", testStruct1.Map)
1727+
assert.Nil(t, testStruct1.MapPtr, "expected nil map ptr, got: %v", testStruct1.MapPtr)
1728+
assert.Nil(t, testStruct1.Ptr, "expected nil ptr, got: %v", testStruct1.Ptr)
17321729

1733-
// b, _ := bson.MarshalWithRegistry(mgoRegistry, testStruct1)
1730+
b, _ := bson.MarshalWithRegistry(mgoRegistryRespectNilValues, testStruct1)
17341731

1735-
// testStruct2 := T{}
1732+
testStruct2 := T{}
17361733

1737-
// _ = bson.UnmarshalWithRegistry(mgoRegistry, b, &testStruct2)
1734+
_ = bson.UnmarshalWithRegistry(mgoRegistryRespectNilValues, b, &testStruct2)
17381735

1739-
// assert.Nil(t, testStruct2.Slice, "expected nil slice, got: %v", testStruct2.Slice)
1740-
// assert.Nil(t, testStruct2.SlicePtr, "expected nil slice ptr, got: %v", testStruct2.SlicePtr)
1741-
// assert.Nil(t, testStruct2.Map, "expected nil map, got: %v", testStruct2.Map)
1742-
// assert.Nil(t, testStruct2.MapPtr, "expected nil map ptr, got: %v", testStruct2.MapPtr)
1743-
// assert.Nil(t, testStruct2.Ptr, "expected nil ptr, got: %v", testStruct2.Ptr)
1736+
assert.Nil(t, testStruct2.Slice, "expected nil slice, got: %v", testStruct2.Slice)
1737+
assert.Nil(t, testStruct2.SlicePtr, "expected nil slice ptr, got: %v", testStruct2.SlicePtr)
1738+
assert.Nil(t, testStruct2.Map, "expected nil map, got: %v", testStruct2.Map)
1739+
assert.Nil(t, testStruct2.MapPtr, "expected nil map ptr, got: %v", testStruct2.MapPtr)
1740+
assert.Nil(t, testStruct2.Ptr, "expected nil ptr, got: %v", testStruct2.Ptr)
17441741

1745-
// testStruct1 = T{
1746-
// Slice: []int{},
1747-
// SlicePtr: &[]int{},
1748-
// Map: map[string]interface{}{},
1749-
// MapPtr: &map[string]interface{}{},
1750-
// }
1742+
testStruct1 = T{
1743+
Slice: []int{},
1744+
SlicePtr: &[]int{},
1745+
Map: map[string]interface{}{},
1746+
MapPtr: &map[string]interface{}{},
1747+
}
17511748

1752-
// assert.NotNil(t, testStruct1.Slice, "expected non-nil slice")
1753-
// assert.NotNil(t, testStruct1.SlicePtr, "expected non-nil slice ptr")
1754-
// assert.NotNil(t, testStruct1.Map, "expected non-nil map")
1755-
// assert.NotNil(t, testStruct1.MapPtr, "expected non-nil map ptr")
1749+
assert.NotNil(t, testStruct1.Slice, "expected non-nil slice")
1750+
assert.NotNil(t, testStruct1.SlicePtr, "expected non-nil slice ptr")
1751+
assert.NotNil(t, testStruct1.Map, "expected non-nil map")
1752+
assert.NotNil(t, testStruct1.MapPtr, "expected non-nil map ptr")
17561753

1757-
// b, _ = bson.MarshalWithRegistry(mgoRegistry, testStruct1)
1754+
b, _ = bson.MarshalWithRegistry(mgoRegistryRespectNilValues, testStruct1)
17581755

1759-
// testStruct2 = T{}
1756+
testStruct2 = T{}
17601757

1761-
// _ = bson.UnmarshalWithRegistry(mgoRegistry, b, &testStruct2)
1758+
_ = bson.UnmarshalWithRegistry(mgoRegistryRespectNilValues, b, &testStruct2)
17621759

1763-
// assert.NotNil(t, testStruct2.Slice, "expected non-nil slice")
1764-
// assert.NotNil(t, testStruct2.SlicePtr, "expected non-nil slice ptr")
1765-
// assert.NotNil(t, testStruct2.Map, "expected non-nil map")
1766-
// assert.NotNil(t, testStruct2.MapPtr, "expected non-nil map ptr")
1767-
// }
1760+
assert.NotNil(t, testStruct2.Slice, "expected non-nil slice")
1761+
assert.NotNil(t, testStruct2.SlicePtr, "expected non-nil slice ptr")
1762+
assert.NotNil(t, testStruct2.Map, "expected non-nil map")
1763+
assert.NotNil(t, testStruct2.MapPtr, "expected non-nil map ptr")
1764+
}

bson/mgocompat/registry.go

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,17 @@ var (
3131
tSetter = reflect.TypeOf((*Setter)(nil)).Elem()
3232
)
3333

34-
// mgoRegistry is the default bsoncodec.Registry. It contains the default codecs and the
35-
// primitive codecs.
36-
var mgoRegistry = newRegistryBuilder().Build()
34+
// mgoRegistry is the mgo compatible bsoncodec.Registry. It contains the default and
35+
// primitive codecs with mgo compatible options.
36+
var mgoRegistry = newMgoRegistryBuilder().Build()
3737

38-
// newRegistryBuilder creates a new RegistryBuilder configured with the default encoders and
38+
// mgoRegistryRespectNilValues is the bsoncodec.Registry compatible with mgo withSetRespectNilValues set to true.
39+
var mgoRegistryRespectNilValues = newMgoRespectNilValuesRegistryBuilder().Build()
40+
41+
// newMgoRegistryBuilder creates a new bsoncodec.RegistryBuilder configured with the default encoders and
3942
// deocders from the bsoncodec.DefaultValueEncoders and bsoncodec.DefaultValueDecoders types and the
4043
// PrimitiveCodecs type in this package.
41-
func newRegistryBuilder() *bsoncodec.RegistryBuilder {
44+
func newMgoRegistryBuilder() *bsoncodec.RegistryBuilder {
4245
rb := bsoncodec.NewRegistryBuilder()
4346
bsoncodec.DefaultValueEncoders{}.RegisterDefaultEncoders(rb)
4447
bsoncodec.DefaultValueDecoders{}.RegisterDefaultDecoders(rb)
@@ -82,3 +85,28 @@ func newRegistryBuilder() *bsoncodec.RegistryBuilder {
8285

8386
return rb
8487
}
88+
89+
// buildMgoRNVRegistry creates a new bsoncodec.RegistryBuilder configured to behave like mgo/bson with RespectNilValues set to true.
90+
func newMgoRespectNilValuesRegistryBuilder() *bsoncodec.RegistryBuilder {
91+
rb := newMgoRegistryBuilder()
92+
93+
structcodec, _ := bsoncodec.NewStructCodec(bsoncodec.DefaultStructTagParser,
94+
bsonoptions.StructCodec().
95+
SetDecodeZeroStruct(true).
96+
SetDecodeDeepZeroInline(false).
97+
SetEncodeOmitDefaultStruct(true).
98+
SetAllowUnexportedFields(true))
99+
mapCodec := bsoncodec.NewMapCodec(
100+
bsonoptions.MapCodec().
101+
SetDecodeZerosMap(true).
102+
SetEncodeNilAsEmpty(false))
103+
104+
rb.RegisterDefaultDecoder(reflect.Struct, structcodec).
105+
RegisterDefaultDecoder(reflect.Map, mapCodec).
106+
RegisterTypeEncoder(tByteSlice, bsoncodec.NewByteSliceCodec(bsonoptions.ByteSliceCodec().SetEncodeNilAsEmpty(false))).
107+
RegisterDefaultEncoder(reflect.Struct, structcodec).
108+
RegisterDefaultEncoder(reflect.Slice, bsoncodec.NewSliceCodec(bsonoptions.SliceCodec().SetEncodeNilAsEmpty(false))).
109+
RegisterDefaultEncoder(reflect.Map, mapCodec)
110+
111+
return rb
112+
}

0 commit comments

Comments
 (0)