1
0
Fork 0
mirror of https://github.com/imjasonh/csvstruct synced 2026-07-18 14:56:23 +00:00

support non-string values, add skipped test for pointers

This commit is contained in:
Jason Hall 2014-05-15 11:22:29 -04:00
parent e351bdc1ec
commit 3eb5423212
2 changed files with 63 additions and 8 deletions

View file

@ -1,7 +1,6 @@
// TODO: support DecodeNext(nil) to skip a line // TODO: support DecodeNext(nil) to skip a line
// TODO: NewEncoder/EncodeNext -- header will be fields in first item... // TODO: NewEncoder/EncodeNext -- header will be fields in first item...
// TODO: Encode/Decode map[string]string // TODO: Encode/Decode map[string]string
// TODO: Encode/Decode non-string values?
// Package csvstruct provides methods to decode a CSV file into a struct. // Package csvstruct provides methods to decode a CSV file into a struct.
package csvstruct package csvstruct
@ -12,6 +11,7 @@ import (
"fmt" "fmt"
"io" "io"
"reflect" "reflect"
"strconv"
) )
// Decoder reads and decodes CSV rows from an input stream. // Decoder reads and decodes CSV rows from an input stream.
@ -69,7 +69,30 @@ func (d *decoder) DecodeNext(v interface{}) error {
strv := line[idx] strv := line[idx]
vf := rv.FieldByName(f.Name) vf := rv.FieldByName(f.Name)
if vf.CanSet() { if vf.CanSet() {
vf.SetString(strv) switch vf.Kind() {
case reflect.String:
vf.SetString(strv)
case reflect.Int, reflect.Int64:
i, err := strconv.ParseInt(strv, 10, 64)
if err != nil {
return fmt.Errorf("error decoding: %v", err)
}
vf.SetInt(i)
case reflect.Float64:
f, err := strconv.ParseFloat(strv, 64)
if err != nil {
return fmt.Errorf("error decoding: %v", err)
}
vf.SetFloat(f)
case reflect.Bool:
b, err := strconv.ParseBool(strv)
if err != nil {
return fmt.Errorf("error decoding: %v", err)
}
vf.SetBool(b)
default:
return fmt.Errorf("can't decode type %v", vf.Type())
}
} }
} }
return nil return nil

View file

@ -64,10 +64,9 @@ func TestDecode_Unexported(t *testing.T) {
type row struct { type row struct {
Exported, unexported string Exported, unexported string
} }
d := NewDecoder(strings.NewReader(`Exported,unexported
a,b`))
var r row var r row
if err := d.DecodeNext(&r); err != nil { if err := NewDecoder(strings.NewReader(`Exported,unexported
a,b`)).DecodeNext(&r); err != nil {
t.Errorf("unexpected error: %v", err) t.Errorf("unexpected error: %v", err)
} }
exp := row{Exported: "a"} exp := row{Exported: "a"}
@ -82,10 +81,9 @@ func TestDecode_Tags(t *testing.T) {
Bar string Bar string
Ignored string `csv:"-"` Ignored string `csv:"-"`
} }
d := NewDecoder(strings.NewReader(`renamed_foo,Bar,Ignored
a,b,c`))
var r row var r row
if err := d.DecodeNext(&r); err != nil { if err := NewDecoder(strings.NewReader(`renamed_foo,Bar,Ignored
a,b,c`)).DecodeNext(&r); err != nil {
t.Errorf("unexpected error: %v", err) t.Errorf("unexpected error: %v", err)
} }
exp := row{"a", "b", ""} exp := row{"a", "b", ""}
@ -93,3 +91,37 @@ a,b,c`))
t.Errorf("unexpected results, got %v, want %v", r, exp) t.Errorf("unexpected results, got %v, want %v", r, exp)
} }
} }
func TestDecode_NonStrings(t *testing.T) {
type row struct {
Int int
Int64 int64
Float64 float64
Bool bool
}
var r row
if err := NewDecoder(strings.NewReader(`Int,Int64,Float64,Bool
123,123456789,123.456,true`)).DecodeNext(&r); err != nil {
t.Errorf("unexpected error: %v", err)
}
exp := row{123, 123456789, 123.456, true}
if !reflect.DeepEqual(r, exp) {
t.Errorf("unexpected results, got %v, want %v", r, exp)
}
}
func TestDecode_Pointers(t *testing.T) {
t.Skip("pointers are not yet supported")
type row struct {
S string
SP *string
}
var r row
if err := NewDecoder(strings.NewReader(`S,SP
a,b`)).DecodeNext(&r); err != nil {
t.Errorf("unexpected error: %v", err)
}
if r.S != "a" || r.SP == nil || *r.SP != "b" {
t.Errorf("unexpected results, got %v", r)
}
}