From d21f39eeebd3586e7faf4d83c7a8e12b6e04c82e Mon Sep 17 00:00:00 2001 From: Victor Häggqvist Date: Tue, 21 Apr 2020 09:34:44 +0200 Subject: replace ini --- vendor/github.com/gocarina/gocsv/unmarshaller.go | 35 +++++++++++++++++++----- 1 file changed, 28 insertions(+), 7 deletions(-) (limited to 'vendor/github.com/gocarina/gocsv/unmarshaller.go') diff --git a/vendor/github.com/gocarina/gocsv/unmarshaller.go b/vendor/github.com/gocarina/gocsv/unmarshaller.go index ace601e..87e6a8f 100644 --- a/vendor/github.com/gocarina/gocsv/unmarshaller.go +++ b/vendor/github.com/gocarina/gocsv/unmarshaller.go @@ -10,7 +10,8 @@ import ( // Unmarshaller is a CSV to struct unmarshaller. type Unmarshaller struct { reader *csv.Reader - fieldInfoMap map[int]*fieldInfo + Headers []string + fieldInfoMap []*fieldInfo MismatchedHeaders []string MismatchedStructFields []string outType reflect.Type @@ -22,6 +23,7 @@ func NewUnmarshaller(reader *csv.Reader, out interface{}) (*Unmarshaller, error) if err != nil { return nil, err } + headers = normalizeHeaders(headers) um := &Unmarshaller{reader: reader, outType: reflect.TypeOf(out)} err = validate(um, out, headers) @@ -38,7 +40,18 @@ func (um *Unmarshaller) Read() (interface{}, error) { if err != nil { return nil, err } - return um.unmarshalRow(row) + return um.unmarshalRow(row, nil) +} + +// ReadUnmatched is same as Read(), but returns a map of the columns that didn't match a field in the struct +func (um *Unmarshaller) ReadUnmatched() (interface{}, map[string]string, error) { + row, err := um.reader.Read() + if err != nil { + return nil, nil, err + } + unmatched := make(map[string]string) + value, err := um.unmarshalRow(row, unmatched) + return value, unmatched, err } // validate ensures that a struct was used to create the Unmarshaller, and validates @@ -55,7 +68,7 @@ func validate(um *Unmarshaller, s interface{}, headers []string) error { if len(structInfo.Fields) == 0 { return errors.New("no csv struct tags found") } - csvHeadersLabels := make(map[int]*fieldInfo, len(structInfo.Fields)) // Used to store the corresponding header <-> position in CSV + csvHeadersLabels := make([]*fieldInfo, len(headers)) // Used to store the corresponding header <-> position in CSV headerCount := map[string]int{} for i, csvColumnHeader := range headers { curHeaderCount := headerCount[csvColumnHeader] @@ -67,10 +80,14 @@ func validate(um *Unmarshaller, s interface{}, headers []string) error { } } } - if err := maybeDoubleHeaderNames(headers); err != nil { - return err + + if FailIfDoubleHeaderNames { + if err := maybeDoubleHeaderNames(headers); err != nil { + return err + } } + um.Headers = headers um.fieldInfoMap = csvHeadersLabels um.MismatchedHeaders = mismatchHeaderFields(structInfo.Fields, headers) um.MismatchedStructFields = mismatchStructFields(structInfo.Fields, headers) @@ -78,7 +95,8 @@ func validate(um *Unmarshaller, s interface{}, headers []string) error { } // unmarshalRow converts a CSV row to a struct, based on CSV struct tags. -func (um *Unmarshaller) unmarshalRow(row []string) (interface{}, error) { +// If unmatched is non nil, it is populated with any columns that don't map to a struct field +func (um *Unmarshaller) unmarshalRow(row []string, unmatched map[string]string) (interface{}, error) { isPointer := false concreteOutType := um.outType if um.outType.Kind() == reflect.Ptr { @@ -87,10 +105,13 @@ func (um *Unmarshaller) unmarshalRow(row []string) (interface{}, error) { } outValue := createNewOutInner(isPointer, concreteOutType) for j, csvColumnContent := range row { - if fieldInfo, ok := um.fieldInfoMap[j]; ok { + if j < len(um.fieldInfoMap) && um.fieldInfoMap[j] != nil { + fieldInfo := um.fieldInfoMap[j] if err := setInnerField(&outValue, isPointer, fieldInfo.IndexChain, csvColumnContent, fieldInfo.omitEmpty); err != nil { // Set field of struct return nil, fmt.Errorf("cannot assign field at %v to %s through index chain %v: %v", j, outValue.Type(), fieldInfo.IndexChain, err) } + } else if unmatched != nil { + unmatched[um.Headers[j]] = csvColumnContent } } return outValue.Interface(), nil -- cgit v1.2.3