csvcoder

package
v0.0.16 Latest Latest
Warning

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

Go to latest
Published: Oct 4, 2021 License: Apache-2.0, BSD-3-Clause Imports: 8 Imported by: 0

Documentation

Overview

Package csvcoder decodes Go types from CSV records using struct tags, similar to encoding/csv and encoding/xml packages in the standard library.

Like the standard library packages for JSON and XML encoding, this package uses tags on struct fields to specify the correspondence of a CSV column with a struct field. See the examples for full usage, but to get a sense of how csvcoder works, observe the following structure definition:

type mass float64

type species struct {
	Name                string `csv:"name"`
	EstimatedPopulation int    `csv:"population_estimate"`
	Mass                mass   `csv:"weight_kg"`
}
csvcoder.RegisterRowStruct(reflect.TypeOf(&species{}))

Unlike the standard library packages, this package uses textcoder for decoding textual values, allowing any package to provide a decoder for a given type rather than using methods of the type.

Example (ARowParsing)
package main

import (
	"fmt"
	"reflect"

	"github.com/google/xtoproto/csvcoder"
)

func main() {
	type mass float64

	type species struct {
		Name string `csv:"name"`
		Mass mass   `csv:"weight_kg"`
	}
	csvcoder.RegisterRowStruct(reflect.TypeOf(&species{}))

	redwood := &species{}
	err := csvcoder.ParseRow(
		csvcoder.NewRow(
			[]string{"Redwood", "1200000"},
			csvcoder.NewHeader([]string{"name", "weight_kg"}),
			csvcoder.RowNumber(10),
			"example.csv"),
		redwood)

	fmt.Printf("error: %v\n", err != nil)
	fmt.Printf("record: name = %q, mass = %f", redwood.Name, redwood.Mass)
}
Output:

error: false
record: name = "Redwood", mass = 1200000.000000
Example (BFileParsing)
package main

import (
	"encoding/csv"
	"fmt"
	"reflect"
	"strings"

	"github.com/google/xtoproto/csvcoder"
)

func main() {
	type mass float64

	type species struct {
		Name string  `csv:"name"`
		Mass float64 `csv:"weight_kg"`
	}
	csvcoder.RegisterRowStruct(reflect.TypeOf(&species{}))

	inputReader := csv.NewReader(strings.NewReader(`name,weight_kg
Redwood,1200000
"Blue whale",200000
`))

	fp, err := csvcoder.NewFileParser(inputReader, "in-memory.csv", &species{})
	if err != nil {
		fmt.Printf("NewFileParser error: %v", err)
		return
	}

	if err := fp.ReadAll(func(i interface{}) error {
		rec := i.(*species)
		fmt.Printf("record: name = %q, mass = %f\n", rec.Name, rec.Mass)
		return nil
	}); err != nil {
		fmt.Printf("ReadAll error: %v\n", err)
	}
}
Output:

record: name = "Redwood", mass = 1200000.000000
record: name = "Blue whale", mass = 200000.000000

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func ParseCell

func ParseCell(ctx *CellContext, value string, dst interface{}) error

ParseCell parses a single CSV cell's textual value into dst.

func ParseRow

func ParseRow(row *Row, destination interface{}) error

ParseRow returns an error if the row fails to parse.

If the destination object has a `ParseCSVRow(*Row) error` method, that method will be called on the destination object.

func RegisterRowStruct

func RegisterRowStruct(t reflect.Type, opt ...RegisterOption)

RegisterRowStruct registers a struct type T that can be encoded as a CSV row.

Each public field of the struct definition will be examined and treated as follows:

1. If the field has a `csv-skip` tag, it will not be parsed.

2. If the field has a `csv` tag, that tag will be treated as the name of the CSV column for the field. If the tag is absent, the column name used will be the name of the field.

3. Let FT be the Go type of the field. If there is a registered decoder for *FT, that decoder will be used to decode the string value of the field with the name from step 2 into the field of a row being parsed. If there is no registered decoder for *FT, RegisterRowStruct will panic and SafeRegisterRowStruct returns an error.

Example
type Pet struct {
	Name         string  `csv:"pet-name"`
	Internal     string  `csv-skip:""`
	WeightPounds float64 `csv:"weight-lb"`
}
RegisterRowStruct(reflect.TypeOf(&Pet{}))

henry := &Pet{}
err := ParseRow(NewRow(
	[]string{"ignored", "Henry", "32.15"},
	NewHeader([]string{"id", "pet-name", "weight-lb"}),
	1,
	"example.csv"),
	henry)

if err != nil {
	fmt.Printf("error: %v", err)
	return
}

fmt.Printf("%q weighs %d pounds", henry.Name, int(henry.WeightPounds))
Output:

"Henry" weighs 32 pounds

func SafeRegisterRowStruct

func SafeRegisterRowStruct(t reflect.Type, opt ...RegisterOption) error

SafeRegisterRowStruct calls RegisterRowStruct but returns an error instead of panicking if there are any issues.

Types

type CellContext

type CellContext struct {
	// contains filtered or unexported fields
}

CellContext is passed to the function parsing a single CSV cell.

func NewCellContext

func NewCellContext(rctx *Row) *CellContext

NewCellContext returns a new CellContext to use when parsing within a given Row.

func (*CellContext) Row

func (c *CellContext) Row() *Row

Row returns the row that is being parsed.

type ColumnNumber

type ColumnNumber int

ColumnNumber is used instead of an int for column indexes.

const InvalidColumn ColumnNumber = -1

InvalidColumn returns an invalid column number.

func (ColumnNumber) IsValid

func (n ColumnNumber) IsValid() bool

IsValid returns whether the column refers to a valid column in the CSV file or or not.

func (ColumnNumber) Offset

func (n ColumnNumber) Offset() int

Offset returns the offset of the value within a row.

type FileParser

type FileParser struct {
	// contains filtered or unexported fields
}

FileParser is an object used to parse an entire CSV file.

func NewFileParser

func NewFileParser(r RowReader, path string, recordPrototype interface{}) (*FileParser, error)

NewFileParser returns an object for parsing a set of records from a file.

The input RowReader will be used to read all rows. The path argument is only for error reporting purposes.

The type of the recordPrototype should have been registered with a call to RegisterRowStruct.

func (*FileParser) Read

func (fp *FileParser) Read() (interface{}, error)

Read parses the next record in the CSV. The header is parsed automatically.

func (*FileParser) ReadAll

func (fp *FileParser) ReadAll(callback func(interface{}) error) error

ReadAll calls Read() until the end of the file and calls cb for each value.

type Header struct {
	// contains filtered or unexported fields
}

Header contains the values of the first row of the CSV file.

func NewHeader

func NewHeader(values []string) *Header

NewHeader returns a Header based on the given values.

func (*Header) ColumnIndex

func (h *Header) ColumnIndex(col string) ColumnNumber

ColumnIndex returns the index of the column with the given name.

func (*Header) ColumnNames

func (h *Header) ColumnNames() []string

ColumnNames returns the names of the columns.

type RegisterOption added in v0.0.6

type RegisterOption struct {
}

RegisterOption objects may be passed to RegisterRowStruct to configure how a type should be parsed as a CSV row.

type Row

type Row struct {
	// contains filtered or unexported fields
}

Row is passed to Unmarshal

func NewRow

func NewRow(values []string, h *Header, num RowNumber, fileName string) *Row

NewRow returns a new parsing context.

func (*Row) Header

func (r *Row) Header() *Header

Header returns the header of the CSV file.

func (*Row) Number

func (r *Row) Number() RowNumber

Number returns the row number.

func (*Row) Path

func (r *Row) Path() string

Path returns the path of the CSV file or empty if this information is not available.

func (*Row) PositionString

func (r *Row) PositionString() string

PositionString returns a human readable representation of the row position.

func (*Row) Strings

func (r *Row) Strings() []string

Strings returns the string values of the row.

type RowNumber

type RowNumber int

RowNumber is used instead of an int for representing the position of a row in a CSV file.

const InvalidRow RowNumber = -1

InvalidRow returns an invalid row number.

func (RowNumber) IsValid

func (n RowNumber) IsValid() bool

IsValid returns whether the row refers to a valid row in the CSV file or or not.

func (RowNumber) Offset

func (n RowNumber) Offset() int

Offset returns the offset of the row. The first row has offset 0.

func (RowNumber) Ordinal

func (n RowNumber) Ordinal() int

Ordinal returns the 1-based offset of the row. The first row has ordinal value 1.

type RowReader added in v0.0.16

type RowReader interface {
	Read() ([]string, error)
}

RowReader is an interface of a reader that reads raw records from the data source. For example, csv.Reader is a RowReader.

Jump to

Keyboard shortcuts

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