Skip to content

Commit

Permalink
SelectedColumns (#6)
Browse files Browse the repository at this point in the history
* fix: README.md

* feat: rename

* tmp

* feat: add test of selectedColumns

* feat: add SelectedColumns
  • Loading branch information
shigetaichi authored Aug 15, 2023
1 parent e005a6f commit c4354d6
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 17 deletions.
3 changes: 0 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@ Most of the programs related to csv generation and reading are created from code
※xsv does not include gocsv.

## 🚧Under Construction
there is a lot of things to do before release.

## Getting Started

```
Expand Down
33 changes: 33 additions & 0 deletions encode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -607,3 +607,36 @@ func Test_writeTo_nested_struct(t *testing.T) {
assertLine(t, []string{"one.boolField1", "one.stringField2", "two.boolField1", "two.stringField2", "three.boolField1", "three.stringField2"}, lines[0])
assertLine(t, []string{"false", "email_one", "true", "email_two", "false", "email_three"}, lines[1])
}

func Test_writeTo_emptyptr_selectedColumns(t *testing.T) {

b := bytes.Buffer{}
e := &encoder{out: &b}
blah := 2
sptr := "*string"
s := []EmbedPtrSample{
{
Qux: "aaa",
Sample: &Sample{Foo: "f", Bar: 1, Baz: "baz", Frop: 0.2, Blah: &blah, SPtr: &sptr},
Ignore: "shouldn't be marshalled",
Quux: "zzz",
Grault: math.Pi,
},
}

xsvWrite := NewXsvWrite[EmbedPtrSample]()
xsvWrite.SelectedColumns = []string{"first", "-", "Baz", "last"} // If a "-" exists here, it will not be output.
if err := xsvWrite.SetWriter(csv.NewWriter(e.out)).Write(s); err != nil {
t.Fatal(err)
}

lines, err := csv.NewReader(&b).ReadAll()
if err != nil {
t.Fatal(err)
}
if len(lines) != 2 {
t.Fatalf("expected 2 lines, got %d", len(lines))
}
assertLine(t, []string{"first", "Baz", "last"}, lines[0])
assertLine(t, []string{"aaa", "baz", "zzz"}, lines[1])
}
36 changes: 25 additions & 11 deletions xsv_write.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,45 @@ import (
"bytes"
"encoding/csv"
"os"
"slices"
)

type XsvWrite[T any] struct {
TagName string //key in the struct field's tag to scan
TagSeparator string //separator string for multiple csv tags in struct fields
OmitHeaders bool
selectedColumnIndex []int // TODO: describe in comment
columnSorter ColumnSorter // TODO: describe in comment
nameNormalizer Normalizer
TagName string //key in the struct field's tag to scan
TagSeparator string //separator string for multiple csv tags in struct fields
OmitHeaders bool
SelectedColumns []string // slice of field names to output
columnSorter ColumnSorter // TODO: describe in comment
nameNormalizer Normalizer
}
type ColumnSorter = func(row []string) []string

func NewXsvWrite[T any]() XsvWrite[T] {
return XsvWrite[T]{
TagName: "csv",
TagSeparator: ",",
OmitHeaders: false,
selectedColumnIndex: make([]int, 0),
TagName: "csv",
TagSeparator: ",",
OmitHeaders: false,
SelectedColumns: make([]string, 0),
columnSorter: func(row []string) []string {
return row
},
nameNormalizer: func(s string) string { return s },
}
}

type ColumnSorter = func(row []string) []string
func (x *XsvWrite[T]) getSelectedFieldInfos(fieldInfos []fieldInfo) []fieldInfo {
if len(x.SelectedColumns) > 0 {
var selectedFieldInfos []fieldInfo
for _, info := range fieldInfos {
if slices.Index(x.SelectedColumns, info.keys[0]) >= 0 {
selectedFieldInfos = append(selectedFieldInfos, info)
}
}
return selectedFieldInfos
} else {
return fieldInfos
}
}

func (x *XsvWrite[T]) SetWriter(writer *csv.Writer) (xw *XsvWriter[T]) {
xw = NewXsvWriter(*x)
Expand Down
5 changes: 2 additions & 3 deletions xsv_writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,9 @@ func (xw *XsvWriter[T]) Write(data []T) error {
}

fieldInfos := getFieldInfos(inInnerType, []int{}, []string{}, xw.TagName, xw.TagSeparator, xw.nameNormalizer) // Get the inner struct info to get CSV annotations
fieldInfos = xw.getSelectedFieldInfos(fieldInfos)
inInnerStructInfo := &structInfo{fieldInfos}

inInnerStructInfo.Fields = getPickedFields(inInnerStructInfo.Fields, xw.selectedColumnIndex) // Filter Fields from all fields

csvHeadersLabels := make([]string, len(inInnerStructInfo.Fields))
for i, fieldInfo := range inInnerStructInfo.Fields { // Used to write the header (first line) in CSV
csvHeadersLabels[i] = fieldInfo.getFirstKey()
Expand Down Expand Up @@ -78,8 +77,8 @@ func (xw *XsvWriter[T]) WriteFromChan(dataChan chan T) error {
}
inInnerWasPointer := inType.Kind() == reflect.Ptr
fieldInfos := getFieldInfos(inType, []int{}, []string{}, xw.TagName, xw.TagSeparator, xw.nameNormalizer) // Get the inner struct info to get CSV annotations
fieldInfos = xw.getSelectedFieldInfos(fieldInfos)
inInnerStructInfo := &structInfo{fieldInfos}
inInnerStructInfo.Fields = getPickedFields(inInnerStructInfo.Fields, xw.selectedColumnIndex) // Filtered out ignoreFields from all fields
csvHeadersLabels := make([]string, len(inInnerStructInfo.Fields))
for i, fieldInfo := range inInnerStructInfo.Fields { // Used to Write the header (first line) in CSV
csvHeadersLabels[i] = fieldInfo.getFirstKey()
Expand Down

0 comments on commit c4354d6

Please sign in to comment.