0
0
Fork 0

Merge pull request #593 from mschoch/add-text-marshaler

add support for mapping to recognize/use TextMarshaler interface
This commit is contained in:
Marty Schoch 2017-05-19 09:54:09 -04:00 committed by GitHub
commit 64c9c61a22
2 changed files with 95 additions and 0 deletions

View File

@ -15,6 +15,7 @@
package mapping
import (
"encoding"
"encoding/json"
"fmt"
"reflect"
@ -481,6 +482,17 @@ func (dm *DocumentMapping) processProperty(property interface{}, path []string,
fieldMapping := newDateTimeFieldMappingDynamic(context.im)
fieldMapping.processTime(property, pathString, path, indexes, context)
}
case encoding.TextMarshaler:
txt, err := property.MarshalText()
if err == nil && subDocMapping != nil {
// index by explicit mapping
for _, fieldMapping := range subDocMapping.Fields {
if fieldMapping.Type == "text" {
fieldMapping.processString(string(txt), pathString, path, indexes, context)
}
}
}
dm.walkDocument(property, path, indexes, context)
default:
if subDocMapping != nil {
for _, fieldMapping := range subDocMapping.Fields {
@ -500,6 +512,23 @@ func (dm *DocumentMapping) processProperty(property interface{}, path []string,
}
}
dm.walkDocument(property, path, indexes, context)
case reflect.Ptr:
switch property := property.(type) {
case encoding.TextMarshaler:
txt, err := property.MarshalText()
if err == nil && subDocMapping != nil {
// index by explicit mapping
for _, fieldMapping := range subDocMapping.Fields {
if fieldMapping.Type == "text" {
fieldMapping.processString(string(txt), pathString, path, indexes, context)
}
}
} else {
dm.walkDocument(property, path, indexes, context)
}
default:
dm.walkDocument(property, path, indexes, context)
}
default:
dm.walkDocument(property, path, indexes, context)
}

View File

@ -900,3 +900,69 @@ func TestMappingForGeo(t *testing.T) {
t.Errorf("expected to find geo point, did not")
}
}
type textMarshalable struct {
body string
Extra string
}
func (t *textMarshalable) MarshalText() ([]byte, error) {
return []byte(t.body), nil
}
func TestMappingForTextMarshaler(t *testing.T) {
tm := struct {
Marshalable *textMarshalable
}{
Marshalable: &textMarshalable{
body: "text",
Extra: "stuff",
},
}
// first verify that when using a mapping that doesn't explicity
// map the stuct field as text, then we traverse inside the struct
// and do our best
m := NewIndexMapping()
doc := document.NewDocument("x")
err := m.MapDocument(doc, tm)
if err != nil {
t.Fatal(err)
}
if len(doc.Fields) != 1 {
t.Fatalf("expected 1 field, got: %d", len(doc.Fields))
}
if doc.Fields[0].Name() != "Marshalable.Extra" {
t.Errorf("expected field to be named 'Marshalable.Extra', got: '%s'", doc.Fields[0].Name())
}
if string(doc.Fields[0].Value()) != tm.Marshalable.Extra {
t.Errorf("expected field value to be '%s', got: '%s'", tm.Marshalable.Extra, string(doc.Fields[0].Value()))
}
// now verify that when a mapping explicity
m = NewIndexMapping()
txt := NewTextFieldMapping()
m.DefaultMapping.AddFieldMappingsAt("Marshalable", txt)
doc = document.NewDocument("x")
err = m.MapDocument(doc, tm)
if err != nil {
t.Fatal(err)
}
if len(doc.Fields) != 1 {
t.Fatalf("expected 1 field, got: %d", len(doc.Fields))
}
if doc.Fields[0].Name() != "Marshalable" {
t.Errorf("expected field to be named 'Marshalable', got: '%s'", doc.Fields[0].Name())
}
want, err := tm.Marshalable.MarshalText()
if err != nil {
t.Fatal(err)
}
if string(doc.Fields[0].Value()) != string(want) {
t.Errorf("expected field value to be '%s', got: '%s'", string(want), string(doc.Fields[0].Value()))
}
}