csvx

package module
v0.0.0-...-b27955f Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 26, 2022 License: Apache-2.0 Imports: 5 Imported by: 0

README

csvx

PkgGoDev

csvx is a package with a CSV string-fields-to-struct encoder and decoder for Go. It makes converting raw strings from CSV files into objects (and vice-versa) much easier.

It is licensed under the permissive Apache 2 license.

Usage

Use with the stdlib csv reader. Use this library to quickly turn []string into an object, or an object into []string.

type targetType struct {
    Name        string `csv:"name"`
    Age         *int   `csv:"age"`
    NonCSVField string // field will be ignored by struct scanner, since it is missing the "csv" tag
}

// decoding

fields := []string{"name", "age"}
decoder := NewDecoder(fields)

target := new(targetType)
err := decoder.Decode([]string{"John Smith","40"}, target)
if err != nil {
    panic(err)
}

fmt.Printf("result: %#v\n", target)

// encoding
encoder := NewEncoder(fields)
records, err := encoder.Encode(target)
if err != nil {
    panic(err)
}

fmt.Printf("records: %#v\n", records)

See also the example on pkg.go.dev and the tests in this package for more examples.

Implemented Types

  • string
  • int
  • int64
  • int32
  • int16
  • int8
  • uint
  • uint64
  • uint32
  • uint16
  • uint8
  • float64
  • float32
  • bool (true, yes, 1, 1.0 = true, false, no, 0, 0.0 = false, other values result in an error, customisable in the Encoder and Decoder fields)
  • struct with encoding.TextUnmarshaler and encoding.TextMarshaler implemented on them
  • Pointer types to above underlying types, e.g. *string (empty string and null result in nil being set on the Go struct)
  • Custom non-struct types, e.g. type Name string, so long as the underlying type is in the list above.

Performance

The struct scanner uses reflect quite heavily, so this library will not be as fast as writing a specific parser for the struct. However, for the vast majority of cases, the performance hit will be acceptable and the development speed increase and simple client code will be worth it!

Auditability/readability

This aims to be a simple, easy-to-audit library with stdlib-only dependencies (github.com/stretchr/testify is also used, but only for test files).

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type CustomDecoderFunc

type CustomDecoderFunc func(val string) (interface{}, error)

type CustomEncoderFunc

type CustomEncoderFunc func(val interface{}) (string, error)

type Decoder

type Decoder struct {
	FieldsMap                   map[string]int
	NullText                    string
	BoolTrueText, BoolFalseText []string
	CustomDecoderMap            map[string]CustomDecoderFunc
}
Example
// setup types. Note "csv" field tag.
type targetType struct {
	Name string `csv:"name"`
	Age  *int   `csv:"age"`
}

fields := []string{"name", "age"}
decoder := NewDecoder(fields)

csvData := bytes.NewBufferString("John Smith,40\nJane Doe,")

var results []*targetType

// use stdlib csv reader to read line by line []string slices
reader := csv.NewReader(csvData)
for {
	valueStrings, err := reader.Read()
	if err != nil {
		if err == io.EOF {
			break
		}

		// unexpected error
		panic(err)
	}

	target := new(targetType)
	err = decoder.Decode(valueStrings, target)
	if err != nil {
		panic(err)
	}

	results = append(results, target)
}

fmt.Printf("Found %d results\n", len(results))
for _, result := range results {
	age := "nil"
	if result.Age != nil {
		age = fmt.Sprintf("%d", *result.Age)
	}
	fmt.Printf("%s: %s\n", result.Name, age)
}
Output:

Found 2 results
John Smith: 40
Jane Doe: nil

func NewDecoder

func NewDecoder(fields []string) *Decoder

func (*Decoder) Decode

func (d *Decoder) Decode(values []string, target interface{}) error

type Encoder

type Encoder struct {
	FieldsMap                   map[string]int
	FloatFmt                    byte
	NullText                    string
	BoolTrueText, BoolFalseText string
	// map[csv tag name]encoder func
	CustomEncoderMap map[string]CustomEncoderFunc
}
Example
type objectType struct {
	ID     int64   `csv:"id"`
	Name   string  `csv:"name"`
	Height float64 `csv:"height"`
}
obj := objectType{
	ID:     123,
	Name:   "Test 987",
	Height: 1.567,
}

encoder := NewEncoder([]string{"id", "name", "height"})

fields, err := encoder.Encode(obj)
if err != nil {
	panic(err)
}

w := csv.NewWriter(os.Stdout)
err = w.Write(fields)
if err != nil {
	panic(err)
}
w.Flush()

err = w.Error()
if err != nil {
	panic(err)
}
Output:

123,Test 987,1.567

func NewEncoder

func NewEncoder(fields []string) *Encoder

func (*Encoder) Encode

func (e *Encoder) Encode(target interface{}) ([]string, error)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL