Skip to content

Commit dc03449

Browse files
steve-graySteelPhase
authored andcommitted
Fallback to JSON tags when BSON tag isn't present (globalsign#91)
* Fallback to JSON tags when BSON tag isn't present Cleanup. * Add test to demonstrate tagging fallback. - Test coverage for tagging test.
1 parent ff8ec98 commit dc03449

File tree

3 files changed

+84
-2
lines changed

3 files changed

+84
-2
lines changed

bson/bson.go

+14-2
Original file line numberDiff line numberDiff line change
@@ -698,9 +698,21 @@ func getStructInfo(st reflect.Type) (*structInfo, error) {
698698
info := fieldInfo{Num: i}
699699

700700
tag := field.Tag.Get("bson")
701-
if tag == "" && strings.Index(string(field.Tag), ":") < 0 {
702-
tag = string(field.Tag)
701+
702+
// Fall-back to JSON struct tag, if feature flag is set.
703+
if tag == "" && useJSONTagFallback {
704+
tag = field.Tag.Get("json")
703705
}
706+
707+
// If there's no bson/json tag available.
708+
if tag == "" {
709+
// If there's no tag, and also no tag: value splits (i.e. no colon)
710+
// then assume the entire tag is the value
711+
if strings.Index(string(field.Tag), ":") < 0 {
712+
tag = string(field.Tag)
713+
}
714+
}
715+
704716
if tag == "-" {
705717
continue
706718
}

bson/compatability_test.go

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package bson_test
2+
3+
import (
4+
"github.com/globalsign/mgo/bson"
5+
. "gopkg.in/check.v1"
6+
)
7+
8+
type mixedTagging struct {
9+
First string
10+
Second string `bson:"second_field"`
11+
Third string `json:"third_field"`
12+
Fourth string `bson:"fourth_field" json:"alternate"`
13+
}
14+
15+
// TestTaggingFallback checks that tagging fallback can be used/works as expected.
16+
func (s *S) TestTaggingFallback(c *C) {
17+
initial := &mixedTagging{
18+
First: "One",
19+
Second: "Two",
20+
Third: "Three",
21+
Fourth: "Four",
22+
}
23+
24+
// Take only testing.T, leave only footprints.
25+
initialState := bson.JSONTagFallbackState()
26+
defer bson.SetJSONTagFallback(initialState)
27+
28+
// Marshal with the new mode applied.
29+
bson.SetJSONTagFallback(true)
30+
bsonState, errBSON := bson.Marshal(initial)
31+
c.Assert(errBSON, IsNil)
32+
33+
// Unmarshal into a generic map so that we can pick up the actual field names
34+
// selected.
35+
target := make(map[string]string)
36+
errUnmarshal := bson.Unmarshal(bsonState, target)
37+
c.Assert(errUnmarshal, IsNil)
38+
39+
// No tag, so standard naming
40+
_, firstExists := target["first"]
41+
c.Assert(firstExists, Equals, true)
42+
43+
// Just a BSON tag
44+
_, secondExists := target["second_field"]
45+
c.Assert(secondExists, Equals, true)
46+
47+
// Just a JSON tag
48+
_, thirdExists := target["third_field"]
49+
c.Assert(thirdExists, Equals, true)
50+
51+
// Should marshal 4th as fourth_field (since we have both tags)
52+
_, fourthExists := target["fourth_field"]
53+
c.Assert(fourthExists, Equals, true)
54+
}

bson/compatibility.go

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package bson
2+
3+
// Current state of the JSON tag fallback option.
4+
var useJSONTagFallback = false
5+
6+
// SetJSONTagFallback enables or disables the JSON-tag fallback for structure tagging. When this is enabled, structures
7+
// without BSON tags on a field will fall-back to using the JSON tag (if present).
8+
func SetJSONTagFallback(state bool) {
9+
useJSONTagFallback = state
10+
}
11+
12+
// JSONTagFallbackState returns the current status of the JSON tag fallback compatability option. See SetJSONTagFallback
13+
// for more information.
14+
func JSONTagFallbackState() bool {
15+
return useJSONTagFallback
16+
}

0 commit comments

Comments
 (0)