Skip to content

Commit

Permalink
Fallback to JSON tags when BSON tag isn't present (globalsign#91)
Browse files Browse the repository at this point in the history
* Fallback to JSON tags when BSON tag isn't present


Cleanup.

* Add test to demonstrate tagging fallback.

- Test coverage for tagging test.
  • Loading branch information
steve-gray authored and SteelPhase committed Feb 20, 2018
1 parent ff8ec98 commit dc03449
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 2 deletions.
16 changes: 14 additions & 2 deletions bson/bson.go
Original file line number Diff line number Diff line change
Expand Up @@ -698,9 +698,21 @@ func getStructInfo(st reflect.Type) (*structInfo, error) {
info := fieldInfo{Num: i}

tag := field.Tag.Get("bson")
if tag == "" && strings.Index(string(field.Tag), ":") < 0 {
tag = string(field.Tag)

// Fall-back to JSON struct tag, if feature flag is set.
if tag == "" && useJSONTagFallback {
tag = field.Tag.Get("json")
}

// If there's no bson/json tag available.
if tag == "" {
// If there's no tag, and also no tag: value splits (i.e. no colon)
// then assume the entire tag is the value
if strings.Index(string(field.Tag), ":") < 0 {
tag = string(field.Tag)
}
}

if tag == "-" {
continue
}
Expand Down
54 changes: 54 additions & 0 deletions bson/compatability_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package bson_test

import (
"github.com/globalsign/mgo/bson"
. "gopkg.in/check.v1"
)

type mixedTagging struct {
First string
Second string `bson:"second_field"`
Third string `json:"third_field"`
Fourth string `bson:"fourth_field" json:"alternate"`
}

// TestTaggingFallback checks that tagging fallback can be used/works as expected.
func (s *S) TestTaggingFallback(c *C) {
initial := &mixedTagging{
First: "One",
Second: "Two",
Third: "Three",
Fourth: "Four",
}

// Take only testing.T, leave only footprints.
initialState := bson.JSONTagFallbackState()
defer bson.SetJSONTagFallback(initialState)

// Marshal with the new mode applied.
bson.SetJSONTagFallback(true)
bsonState, errBSON := bson.Marshal(initial)
c.Assert(errBSON, IsNil)

// Unmarshal into a generic map so that we can pick up the actual field names
// selected.
target := make(map[string]string)
errUnmarshal := bson.Unmarshal(bsonState, target)
c.Assert(errUnmarshal, IsNil)

// No tag, so standard naming
_, firstExists := target["first"]
c.Assert(firstExists, Equals, true)

// Just a BSON tag
_, secondExists := target["second_field"]
c.Assert(secondExists, Equals, true)

// Just a JSON tag
_, thirdExists := target["third_field"]
c.Assert(thirdExists, Equals, true)

// Should marshal 4th as fourth_field (since we have both tags)
_, fourthExists := target["fourth_field"]
c.Assert(fourthExists, Equals, true)
}
16 changes: 16 additions & 0 deletions bson/compatibility.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package bson

// Current state of the JSON tag fallback option.
var useJSONTagFallback = false

// SetJSONTagFallback enables or disables the JSON-tag fallback for structure tagging. When this is enabled, structures
// without BSON tags on a field will fall-back to using the JSON tag (if present).
func SetJSONTagFallback(state bool) {
useJSONTagFallback = state
}

// JSONTagFallbackState returns the current status of the JSON tag fallback compatability option. See SetJSONTagFallback
// for more information.
func JSONTagFallbackState() bool {
return useJSONTagFallback
}

0 comments on commit dc03449

Please sign in to comment.