Skip to content

Commit 113d396

Browse files
authored
Release/r2018.06.15 (#191)
* allow ptr in inline structs * inline pointer_to_struce mode: update comments. return error on pointer not to struct * fix(dbtest): Use os.Kill on windows instead of Interrupt 🐛 I've added a use for os.Kill, instead of os.Interrupt signal, when using Windows. I'm current developing my project on Windows, and using DBServer.Stop() was resulting in: "timeout waiting for mongod process to die". After investigating, I've discovered that os.Interrupt isn't implemented on Windows, and it seems golang has Frozen this issue due to age (2013). They instruct to use os.Kill instead. Using this, the DBServer on my project works with no problem. * Respect nil slices, maps in bson encoder (#147) * socket: only send client metadata once per socket (#105) Periodic cluster synchronisation calls isMaster() which currently resends the "client" metadata every call - the spec specifies: isMaster commands issued after the initial connection handshake MUST NOT contain handshake arguments https://github.com/mongodb/specifications/blob/master/source/mongodb-handshake/handshake.rst#connection-handshake This hotfix prevents subsequent isMaster calls from sending the client metadata again - fixes #101 and fixes #103. Thanks to @changwoo-nam @qhenkart @canthefason @jyoon17 for spotting the initial issue, opening tickets, and having the problem debugged with a PoC fix before I even woke up. * Merge Development (#111) * Brings in a patch on having flusher not suppress errors. (#81) go-mgo#360 * Fallback to JSON tags when BSON tag isn't present (#91) * Fallback to JSON tags when BSON tag isn't present Cleanup. * Add test to demonstrate tagging fallback. - Test coverage for tagging test. * socket: only send client metadata once per socket Periodic cluster synchronisation calls isMaster() which currently resends the "client" metadata every call - the spec specifies: isMaster commands issued after the initial connection handshake MUST NOT contain handshake arguments https://github.com/mongodb/specifications/blob/master/source/mongodb-handshake/handshake.rst#connection-handshake This hotfix prevents subsequent isMaster calls from sending the client metadata again - fixes #101 and fixes #103. Thanks to @changwoo-nam @qhenkart @canthefason @jyoon17 for spotting the initial issue, opening tickets, and having the problem debugged with a PoC fix before I even woke up. * Cluster abended test 254 (#100) * Add a test that mongo Server gets their abended reset as necessary. See https://github.com/go-mgo/mgo/issues/254 and https://github.com/go-mgo/mgo/pull/255/files * Include the patch from Issue 255. This brings in a test which fails without the patch, and passes with the patch. Still to be tested, manual tcpkill of a socket. * changeStream support (#97) Add $changeStream support * readme: credit @peterdeka and @steve-gray (#110) * Hotfix #120 (#136) * cluster: fix deadlock in cluster synchronisation (#120) For a impressively thorough breakdown of the problem, see: #120 (comment) Huge thanks to @dvic and @KJTsanaktsidis for the report and fix. * readme: credit @dvic and @KJTsanaktsidis * added support for marshalling/unmarshalling maps with non-string keys * refactor method receiver * added support for json-compatible support for slices and maps Marshal() func: nil slice or map converts to nil, not empty (initialized with len=0) * fix IsNil on slices and maps format * added godoc * fix sasl empty payload * fix scram-sha-1 auth * revert fix sasl empty payload * Separate read/write network timeouts (#161) * socket: separate read/write network timeouts Splits DialInfo.Timeout (defaults to 60s when using mgo.Dial()) into ReadTimeout and WriteTimeout to address #160. Read/write timeout defaults to DialInfo.Timeout to preserve existing behaviour. * cluster: remove AcquireSocket Only used by tests, replaced by the pool-aware acquire socket functions: * AcquireSocketWithPoolTimeout * AcquireSocketWithBlocking * cluster: use configured timeouts for cluster operations * `mongoCluster.syncServer()` no longer uses hard-coded 5 seconds * `mongoCluster.isMaster()` no longer uses hard-coded 10 seconds * tests: use DialInfo for internal timeouts * server: fix fantastic serverTags nil slice bug When unmarshalling serverTags, it is now an empty slice, instead of a nil slice. `len(thing) == 0` works all the time, regardless. * cluster: remove unused duplicate pool config * session: avoid calculating default values in hot path Changes `DialWithInfo` to handle setting default values by setting the relevant `DialInfo` field, rather than calling the respective methods in the hot path for: * `PoolLimit` * `ReadTimeout` * `WriteTimeout` * session: remove unused consts * session: update docs * add URI options: "w", "j", "wtimeoutMS" (#162) * add URI options: "w", "j", "wtimeoutMS" * change "w" to "j" * Add Collation support for calling Count() on a Query (#166) * Expand documentation for *Iter.Next (#163) The documentation now explains the difference between calling Err and Close after Next returns false. The example code has been expanded to include checking for timeout. * add NewMongoTimestamp() and MongoTimestamp.Time(),Counter() (#171) code is inspired by go-mgo#202 * MGO-156 Avoid iter.Next deadlock on dead sockets (#182) * Allow passing slice pointer as an interface pointer to Iter.All (#181) * socket: only send client metadata once per socket (#105) Periodic cluster synchronisation calls isMaster() which currently resends the "client" metadata every call - the spec specifies: isMaster commands issued after the initial connection handshake MUST NOT contain handshake arguments https://github.com/mongodb/specifications/blob/master/source/mongodb-handshake/handshake.rst#connection-handshake This hotfix prevents subsequent isMaster calls from sending the client metadata again - fixes #101 and fixes #103. Thanks to @changwoo-nam @qhenkart @canthefason @jyoon17 for spotting the initial issue, opening tickets, and having the problem debugged with a PoC fix before I even woke up. * Merge Development (#111) * Brings in a patch on having flusher not suppress errors. (#81) go-mgo#360 * Fallback to JSON tags when BSON tag isn't present (#91) * Fallback to JSON tags when BSON tag isn't present Cleanup. * Add test to demonstrate tagging fallback. - Test coverage for tagging test. * socket: only send client metadata once per socket Periodic cluster synchronisation calls isMaster() which currently resends the "client" metadata every call - the spec specifies: isMaster commands issued after the initial connection handshake MUST NOT contain handshake arguments https://github.com/mongodb/specifications/blob/master/source/mongodb-handshake/handshake.rst#connection-handshake This hotfix prevents subsequent isMaster calls from sending the client metadata again - fixes #101 and fixes #103. Thanks to @changwoo-nam @qhenkart @canthefason @jyoon17 for spotting the initial issue, opening tickets, and having the problem debugged with a PoC fix before I even woke up. * Cluster abended test 254 (#100) * Add a test that mongo Server gets their abended reset as necessary. See https://github.com/go-mgo/mgo/issues/254 and https://github.com/go-mgo/mgo/pull/255/files * Include the patch from Issue 255. This brings in a test which fails without the patch, and passes with the patch. Still to be tested, manual tcpkill of a socket. * changeStream support (#97) Add $changeStream support * readme: credit @peterdeka and @steve-gray (#110) * Hotfix #120 (#136) * cluster: fix deadlock in cluster synchronisation (#120) For a impressively thorough breakdown of the problem, see: #120 (comment) Huge thanks to @dvic and @KJTsanaktsidis for the report and fix. * readme: credit @dvic and @KJTsanaktsidis * Allow passing slice pointer as an interface pointer to Iter.All * Reverted to original error message, added test case for interface{} ptr * Contributing:findAndModify support writeConcern (#185) * socket: only send client metadata once per socket (#105) Periodic cluster synchronisation calls isMaster() which currently resends the "client" metadata every call - the spec specifies: isMaster commands issued after the initial connection handshake MUST NOT contain handshake arguments https://github.com/mongodb/specifications/blob/master/source/mongodb-handshake/handshake.rst#connection-handshake This hotfix prevents subsequent isMaster calls from sending the client metadata again - fixes #101 and fixes #103. Thanks to @changwoo-nam @qhenkart @canthefason @jyoon17 for spotting the initial issue, opening tickets, and having the problem debugged with a PoC fix before I even woke up. * Merge Development (#111) * Brings in a patch on having flusher not suppress errors. (#81) go-mgo#360 * Fallback to JSON tags when BSON tag isn't present (#91) * Fallback to JSON tags when BSON tag isn't present Cleanup. * Add test to demonstrate tagging fallback. - Test coverage for tagging test. * socket: only send client metadata once per socket Periodic cluster synchronisation calls isMaster() which currently resends the "client" metadata every call - the spec specifies: isMaster commands issued after the initial connection handshake MUST NOT contain handshake arguments https://github.com/mongodb/specifications/blob/master/source/mongodb-handshake/handshake.rst#connection-handshake This hotfix prevents subsequent isMaster calls from sending the client metadata again - fixes #101 and fixes #103. Thanks to @changwoo-nam @qhenkart @canthefason @jyoon17 for spotting the initial issue, opening tickets, and having the problem debugged with a PoC fix before I even woke up. * Cluster abended test 254 (#100) * Add a test that mongo Server gets their abended reset as necessary. See https://github.com/go-mgo/mgo/issues/254 and https://github.com/go-mgo/mgo/pull/255/files * Include the patch from Issue 255. This brings in a test which fails without the patch, and passes with the patch. Still to be tested, manual tcpkill of a socket. * changeStream support (#97) Add $changeStream support * readme: credit @peterdeka and @steve-gray (#110) * Hotfix #120 (#136) * cluster: fix deadlock in cluster synchronisation (#120) For a impressively thorough breakdown of the problem, see: #120 (comment) Huge thanks to @dvic and @KJTsanaktsidis for the report and fix. * readme: credit @dvic and @KJTsanaktsidis * findAndModify support writeConcern * fix * readme: credit everyone (#187) * @cedric-cordenier * @DaytonG * @ddspog * @gedge * @jefferickson * @larrycinnabar * @Mei-Zhao * @roobre * revert: MGO-156 Avoid iter.Next deadlock on dead sockets (#182) (#188) This reverts commit 7253b2b. * Add support for ssl dial string (#184) * Add support for ssl dial string * Ensure we dont override user settings * update examples * update ssl value parsing * PingSsl test * skip test requiring system certificates * readme: credit @tbruyelle (#190)
1 parent efe0945 commit 113d396

18 files changed

+818
-218
lines changed

README.md

+19-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ A [sub-package](https://godoc.org/github.com/globalsign/mgo/bson) that implement
3131
* Supports dropping all indexes on a collection ([details](https://github.com/globalsign/mgo/pull/25))
3232
* Annotates log entries/profiler output with optional appName on 3.4+ ([details](https://github.com/globalsign/mgo/pull/28))
3333
* Support for read-only [views](https://docs.mongodb.com/manual/core/views/) in 3.4+ ([details](https://github.com/globalsign/mgo/pull/33))
34-
* Support for [collations](https://docs.mongodb.com/manual/reference/collation/) in 3.4+ ([details](https://github.com/globalsign/mgo/pull/37))
34+
* Support for [collations](https://docs.mongodb.com/manual/reference/collation/) in 3.4+ ([details](https://github.com/globalsign/mgo/pull/37), [more](https://github.com/globalsign/mgo/pull/166))
3535
* Provide BSON constants for convenience/sanity ([details](https://github.com/globalsign/mgo/pull/41))
3636
* Consistently unmarshal time.Time values as UTC ([details](https://github.com/globalsign/mgo/pull/42))
3737
* Enforces best practise coding guidelines ([details](https://github.com/globalsign/mgo/pull/44))
@@ -49,6 +49,15 @@ A [sub-package](https://godoc.org/github.com/globalsign/mgo/bson) that implement
4949
* Add BSON stream encoders ([details](https://github.com/globalsign/mgo/pull/127))
5050
* Add integer map key support in the BSON encoder ([details](https://github.com/globalsign/mgo/pull/140))
5151
* Support aggregation [collations](https://docs.mongodb.com/manual/reference/collation/) ([details](https://github.com/globalsign/mgo/pull/144))
52+
* Support encoding of inline struct references ([details](https://github.com/globalsign/mgo/pull/146))
53+
* Improved windows test harness ([details](https://github.com/globalsign/mgo/pull/158))
54+
* Improved type and nil handling in the BSON codec ([details](https://github.com/globalsign/mgo/pull/147/files), [more](https://github.com/globalsign/mgo/pull/181))
55+
* Separated network read/write timeouts ([details](https://github.com/globalsign/mgo/pull/161))
56+
* Expanded dial string configuration options ([details](https://github.com/globalsign/mgo/pull/162))
57+
* Implement MongoTimestamp ([details](https://github.com/globalsign/mgo/pull/171))
58+
* Support setting `writeConcern` for `findAndModify` operations ([details](https://github.com/globalsign/mgo/pull/185))
59+
* Add `ssl` to the dial string options ([details](https://github.com/globalsign/mgo/pull/184))
60+
5261

5362
---
5463

@@ -59,23 +68,32 @@ A [sub-package](https://godoc.org/github.com/globalsign/mgo/bson) that implement
5968
* @BenLubar
6069
* @carldunham
6170
* @carter2000
71+
* @cedric-cordenier
6272
* @cezarsa
73+
* @DaytonG
74+
* @ddspog
6375
* @drichelson
6476
* @dvic
6577
* @eaglerayp
6678
* @feliixx
6779
* @fmpwizard
6880
* @gazoon
81+
* @gedge
6982
* @gnawux
7083
* @idy
7184
* @jameinel
85+
* @jefferickson
7286
* @johnlawsharrison
7387
* @KJTsanaktsidis
88+
* @larrycinnabar
7489
* @mapete94
7590
* @maxnoel
7691
* @mcspring
92+
* @Mei-Zhao
7793
* @peterdeka
7894
* @Reenjii
95+
* @roobre
7996
* @smoya
8097
* @steve-gray
98+
* @tbruyelle
8199
* @wgallagher

bson/bson.go

+40-1
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import (
4242
"errors"
4343
"fmt"
4444
"io"
45+
"math"
4546
"os"
4647
"reflect"
4748
"runtime"
@@ -426,6 +427,36 @@ func Now() time.Time {
426427
// strange reason has its own datatype defined in BSON.
427428
type MongoTimestamp int64
428429

430+
// Time returns the time part of ts which is stored with second precision.
431+
func (ts MongoTimestamp) Time() time.Time {
432+
return time.Unix(int64(uint64(ts)>>32), 0)
433+
}
434+
435+
// Counter returns the counter part of ts.
436+
func (ts MongoTimestamp) Counter() uint32 {
437+
return uint32(ts)
438+
}
439+
440+
// NewMongoTimestamp creates a timestamp using the given
441+
// date `t` (with second precision) and counter `c` (unique for `t`).
442+
//
443+
// Returns an error if time `t` is not between 1970-01-01T00:00:00Z
444+
// and 2106-02-07T06:28:15Z (inclusive).
445+
//
446+
// Note that two MongoTimestamps should never have the same (time, counter) combination:
447+
// the caller must ensure the counter `c` is increased if creating multiple MongoTimestamp
448+
// values for the same time `t` (ignoring fractions of seconds).
449+
func NewMongoTimestamp(t time.Time, c uint32) (MongoTimestamp, error) {
450+
u := t.Unix()
451+
if u < 0 || u > math.MaxUint32 {
452+
return -1, errors.New("invalid value for time")
453+
}
454+
455+
i := int64(u<<32 | int64(c))
456+
457+
return MongoTimestamp(i), nil
458+
}
459+
429460
type orderKey int64
430461

431462
// MaxKey is a special value that compares higher than all other possible BSON
@@ -746,6 +777,14 @@ func getStructInfo(st reflect.Type) (*structInfo, error) {
746777
return nil, errors.New("Option ,inline needs a map with string keys in struct " + st.String())
747778
}
748779
inlineMap = info.Num
780+
case reflect.Ptr:
781+
// allow only pointer to struct
782+
if kind := field.Type.Elem().Kind(); kind != reflect.Struct {
783+
return nil, errors.New("Option ,inline allows a pointer only to a struct, was given pointer to " + kind.String())
784+
}
785+
786+
field.Type = field.Type.Elem()
787+
fallthrough
749788
case reflect.Struct:
750789
sinfo, err := getStructInfo(field.Type)
751790
if err != nil {
@@ -765,7 +804,7 @@ func getStructInfo(st reflect.Type) (*structInfo, error) {
765804
fieldsList = append(fieldsList, finfo)
766805
}
767806
default:
768-
panic("Option ,inline needs a struct value or map field")
807+
panic("Option ,inline needs a struct value or a pointer to a struct or map field")
769808
}
770809
continue
771810
}

bson/bson_test.go

+158-9
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ import (
3232
"encoding/json"
3333
"encoding/xml"
3434
"errors"
35+
"fmt"
36+
"math/rand"
3537
"net/url"
3638
"reflect"
3739
"strings"
@@ -271,6 +273,42 @@ func (s *S) TestMarshalBuffer(c *C) {
271273
c.Assert(data, DeepEquals, buf[:len(data)])
272274
}
273275

276+
func (s *S) TestPtrInline(c *C) {
277+
cases := []struct {
278+
In interface{}
279+
Out bson.M
280+
}{
281+
{
282+
In: inlinePtrStruct{A: 1, MStruct: &MStruct{M: 3}},
283+
Out: bson.M{"a": 1, "m": 3},
284+
},
285+
{ // go deeper
286+
In: inlinePtrPtrStruct{B: 10, inlinePtrStruct: &inlinePtrStruct{A: 20, MStruct: &MStruct{M: 30}}},
287+
Out: bson.M{"b": 10, "a": 20, "m": 30},
288+
},
289+
{
290+
// nil embed struct
291+
In: &inlinePtrStruct{A: 3},
292+
Out: bson.M{"a": 3},
293+
},
294+
{
295+
// nil embed struct
296+
In: &inlinePtrPtrStruct{B: 5},
297+
Out: bson.M{"b": 5},
298+
},
299+
}
300+
301+
for _, cs := range cases {
302+
data, err := bson.Marshal(cs.In)
303+
c.Assert(err, IsNil)
304+
var dataBSON bson.M
305+
err = bson.Unmarshal(data, &dataBSON)
306+
c.Assert(err, IsNil)
307+
308+
c.Assert(dataBSON, DeepEquals, cs.Out)
309+
}
310+
}
311+
274312
// --------------------------------------------------------------------------
275313
// Some one way marshaling operations which would unmarshal differently.
276314

@@ -713,8 +751,6 @@ var marshalErrorItems = []testItemType{
713751
"Attempted to marshal empty Raw document"},
714752
{bson.M{"w": bson.Raw{Kind: 0x3, Data: []byte{}}},
715753
"Attempted to marshal empty Raw document"},
716-
{&inlineCantPtr{&struct{ A, B int }{1, 2}},
717-
"Option ,inline needs a struct value or map field"},
718754
{&inlineDupName{1, struct{ A, B int }{2, 3}},
719755
"Duplicated key 'a' in struct bson_test.inlineDupName"},
720756
{&inlineDupMap{},
@@ -1171,8 +1207,19 @@ type inlineBadKeyMap struct {
11711207
M map[int]int `bson:",inline"`
11721208
}
11731209
type inlineUnexported struct {
1174-
M map[string]interface{} `bson:",inline"`
1175-
unexported `bson:",inline"`
1210+
M map[string]interface{} `bson:",inline"`
1211+
unexported `bson:",inline"`
1212+
}
1213+
type MStruct struct {
1214+
M int `bson:"m,omitempty"`
1215+
}
1216+
type inlinePtrStruct struct {
1217+
A int
1218+
*MStruct `bson:",inline"`
1219+
}
1220+
type inlinePtrPtrStruct struct {
1221+
B int
1222+
*inlinePtrStruct `bson:",inline"`
11761223
}
11771224
type unexported struct {
11781225
A int
@@ -1229,11 +1276,11 @@ func (s ifaceSlice) GetBSON() (interface{}, error) {
12291276

12301277
type (
12311278
MyString string
1232-
MyBytes []byte
1233-
MyBool bool
1234-
MyD []bson.DocElem
1235-
MyRawD []bson.RawDocElem
1236-
MyM map[string]interface{}
1279+
MyBytes []byte
1280+
MyBool bool
1281+
MyD []bson.DocElem
1282+
MyRawD []bson.RawDocElem
1283+
MyM map[string]interface{}
12371284
)
12381285

12391286
var (
@@ -1888,3 +1935,105 @@ func (s *S) BenchmarkNewObjectId(c *C) {
18881935
bson.NewObjectId()
18891936
}
18901937
}
1938+
1939+
func (s *S) TestMarshalRespectNil(c *C) {
1940+
type T struct {
1941+
Slice []int
1942+
SlicePtr *[]int
1943+
Ptr *int
1944+
Map map[string]interface{}
1945+
MapPtr *map[string]interface{}
1946+
}
1947+
1948+
bson.SetRespectNilValues(true)
1949+
defer bson.SetRespectNilValues(false)
1950+
1951+
testStruct1 := T{}
1952+
1953+
c.Assert(testStruct1.Slice, IsNil)
1954+
c.Assert(testStruct1.SlicePtr, IsNil)
1955+
c.Assert(testStruct1.Map, IsNil)
1956+
c.Assert(testStruct1.MapPtr, IsNil)
1957+
c.Assert(testStruct1.Ptr, IsNil)
1958+
1959+
b, _ := bson.Marshal(testStruct1)
1960+
1961+
testStruct2 := T{}
1962+
1963+
bson.Unmarshal(b, &testStruct2)
1964+
1965+
c.Assert(testStruct2.Slice, IsNil)
1966+
c.Assert(testStruct2.SlicePtr, IsNil)
1967+
c.Assert(testStruct2.Map, IsNil)
1968+
c.Assert(testStruct2.MapPtr, IsNil)
1969+
c.Assert(testStruct2.Ptr, IsNil)
1970+
1971+
testStruct1 = T{
1972+
Slice: []int{},
1973+
SlicePtr: &[]int{},
1974+
Map: map[string]interface{}{},
1975+
MapPtr: &map[string]interface{}{},
1976+
}
1977+
1978+
c.Assert(testStruct1.Slice, NotNil)
1979+
c.Assert(testStruct1.SlicePtr, NotNil)
1980+
c.Assert(testStruct1.Map, NotNil)
1981+
c.Assert(testStruct1.MapPtr, NotNil)
1982+
1983+
b, _ = bson.Marshal(testStruct1)
1984+
1985+
testStruct2 = T{}
1986+
1987+
bson.Unmarshal(b, &testStruct2)
1988+
1989+
c.Assert(testStruct2.Slice, NotNil)
1990+
c.Assert(testStruct2.SlicePtr, NotNil)
1991+
c.Assert(testStruct2.Map, NotNil)
1992+
c.Assert(testStruct2.MapPtr, NotNil)
1993+
}
1994+
1995+
func (s *S) TestMongoTimestampTime(c *C) {
1996+
t := time.Now()
1997+
ts, err := bson.NewMongoTimestamp(t, 123)
1998+
c.Assert(err, IsNil)
1999+
c.Assert(ts.Time().Unix(), Equals, t.Unix())
2000+
}
2001+
2002+
func (s *S) TestMongoTimestampCounter(c *C) {
2003+
rnd := rand.Uint32()
2004+
ts, err := bson.NewMongoTimestamp(time.Now(), rnd)
2005+
c.Assert(err, IsNil)
2006+
c.Assert(ts.Counter(), Equals, rnd)
2007+
}
2008+
2009+
func (s *S) TestMongoTimestampError(c *C) {
2010+
t := time.Date(1969, time.December, 31, 23, 59, 59, 999, time.UTC)
2011+
ts, err := bson.NewMongoTimestamp(t, 321)
2012+
c.Assert(int64(ts), Equals, int64(-1))
2013+
c.Assert(err, ErrorMatches, "invalid value for time")
2014+
}
2015+
2016+
func ExampleNewMongoTimestamp() {
2017+
2018+
var counter uint32 = 1
2019+
var t time.Time
2020+
2021+
for i := 1; i <= 3; i++ {
2022+
2023+
if c := time.Now(); t.Unix() == c.Unix() {
2024+
counter++
2025+
} else {
2026+
t = c
2027+
counter = 1
2028+
}
2029+
2030+
ts, err := bson.NewMongoTimestamp(t, counter)
2031+
if err != nil {
2032+
fmt.Printf("NewMongoTimestamp error: %v", err)
2033+
} else {
2034+
fmt.Printf("NewMongoTimestamp encoded timestamp: %d\n", ts)
2035+
}
2036+
2037+
time.Sleep(500 * time.Millisecond)
2038+
}
2039+
}

bson/compatibility.go

+14-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
package bson
22

3-
// Current state of the JSON tag fallback option.
3+
// Current state of the JSON tag fallback option.
44
var useJSONTagFallback = false
5+
var useRespectNilValues = false
56

67
// SetJSONTagFallback enables or disables the JSON-tag fallback for structure tagging. When this is enabled, structures
78
// without BSON tags on a field will fall-back to using the JSON tag (if present).
@@ -14,3 +15,15 @@ func SetJSONTagFallback(state bool) {
1415
func JSONTagFallbackState() bool {
1516
return useJSONTagFallback
1617
}
18+
19+
// SetRespectNilValues enables or disables serializing nil slices or maps to `null` values.
20+
// In other words it enables `encoding/json` compatible behaviour.
21+
func SetRespectNilValues(state bool) {
22+
useRespectNilValues = state
23+
}
24+
25+
// RespectNilValuesState returns the current status of the JSON nil slices and maps fallback compatibility option.
26+
// See SetRespectNilValues for more information.
27+
func RespectNilValuesState() bool {
28+
return useRespectNilValues
29+
}

0 commit comments

Comments
 (0)