diff --git a/mapping/document.go b/mapping/document.go index bc473fe6..54bf61b6 100644 --- a/mapping/document.go +++ b/mapping/document.go @@ -42,6 +42,9 @@ type DocumentMapping struct { Properties map[string]*DocumentMapping `json:"properties,omitempty"` Fields []*FieldMapping `json:"fields,omitempty"` DefaultAnalyzer string `json:"default_analyzer"` + + // StructTagKey overrides "json" when looking for field names in struct tags + StructTagKey string `json:"struct_tag_key,omitempty"` } func (dm *DocumentMapping) Validate(cache *registry.Cache) error { @@ -285,6 +288,11 @@ func (dm *DocumentMapping) UnmarshalJSON(data []byte) error { if err != nil { return err } + case "struct_tag_key": + err := json.Unmarshal(v, &dm.StructTagKey) + if err != nil { + return err + } default: invalidKeys = append(invalidKeys, k) } @@ -314,6 +322,12 @@ func (dm *DocumentMapping) defaultAnalyzerName(path []string) string { } func (dm *DocumentMapping) walkDocument(data interface{}, path []string, indexes []uint64, context *walkContext) { + // allow default "json" tag to be overriden + structTagKey := dm.StructTagKey + if structTagKey == "" { + structTagKey = "json" + } + val := reflect.ValueOf(data) typ := val.Type() switch typ.Kind() { @@ -335,15 +349,15 @@ func (dm *DocumentMapping) walkDocument(data interface{}, path []string, indexes fieldName = "" } - // if the field has a JSON name, prefer that - jsonTag := field.Tag.Get("json") - jsonFieldName := parseJSONTagName(jsonTag) - if jsonFieldName == "-" { + // if the field has a name under the specified tag, prefer that + tag := field.Tag.Get(structTagKey) + tagFieldName := parseTagName(tag) + if tagFieldName == "-" { continue } - // allow json tag to set field name to empty, only if anonymous - if field.Tag != "" && (jsonFieldName != "" || field.Anonymous) { - fieldName = jsonFieldName + // allow tag to set field name to empty, only if anonymous + if field.Tag != "" && (tagFieldName != "" || field.Anonymous) { + fieldName = tagFieldName } if val.Field(i).CanInterface() { diff --git a/mapping/mapping_test.go b/mapping/mapping_test.go index fc4cda94..096219ca 100644 --- a/mapping/mapping_test.go +++ b/mapping/mapping_test.go @@ -160,6 +160,88 @@ func TestMappingStructWithJSONTagsOneDisabled(t *testing.T) { } } +func TestMappingStructWithAlternateTags(t *testing.T) { + + mapping := buildMapping() + mapping.(*IndexMappingImpl).DefaultMapping.StructTagKey = "bleve" + + x := struct { + NoBLEVETag string + Name string `bleve:"name"` + }{ + Name: "marty", + } + + doc := document.NewDocument("1") + err := mapping.MapDocument(doc, x) + if err != nil { + t.Fatal(err) + } + foundBLEVEName := false + foundNoBLEVEName := false + count := 0 + for _, f := range doc.Fields { + if f.Name() == "name" { + foundBLEVEName = true + } + if f.Name() == "NoBLEVETag" { + foundNoBLEVEName = true + } + count++ + } + if !foundBLEVEName { + t.Errorf("expected to find field named 'name'") + } + if !foundNoBLEVEName { + t.Errorf("expected to find field named 'NoBLEVETag'") + } + if count != 2 { + t.Errorf("expected to find 2 find, found %d", count) + } +} + +func TestMappingStructWithAlternateTagsTwoDisabled(t *testing.T) { + + mapping := buildMapping() + mapping.(*IndexMappingImpl).DefaultMapping.StructTagKey = "bleve" + + x := struct { + Name string `json:"-" bleve:"name"` + Title string `json:"-" bleve:"-"` + NoBLEVETag string `json:"-"` + Extra string `json:"extra" bleve:"-"` + }{ + Name: "marty", + } + + doc := document.NewDocument("1") + err := mapping.MapDocument(doc, x) + if err != nil { + t.Fatal(err) + } + foundBLEVEName := false + foundNoBLEVEName := false + count := 0 + for _, f := range doc.Fields { + if f.Name() == "name" { + foundBLEVEName = true + } + if f.Name() == "NoBLEVETag" { + foundNoBLEVEName = true + } + count++ + } + if !foundBLEVEName { + t.Errorf("expected to find field named 'name'") + } + if !foundNoBLEVEName { + t.Errorf("expected to find field named 'NoBLEVETag'") + } + if count != 2 { + t.Errorf("expected to find 2 find, found %d", count) + } +} + func TestMappingStructWithPointerToString(t *testing.T) { mapping := buildMapping() diff --git a/mapping/reflect.go b/mapping/reflect.go index 68ff15b4..59bde993 100644 --- a/mapping/reflect.go +++ b/mapping/reflect.go @@ -75,8 +75,8 @@ func mustString(data interface{}) (string, bool) { return "", false } -// parseJSONTagName extracts the JSON field name from a struct tag -func parseJSONTagName(tag string) string { +// parseTagName extracts the field name from a struct tag +func parseTagName(tag string) string { if idx := strings.Index(tag, ","); idx != -1 { return tag[:idx] }