Documentation
¶
Index ¶
- Constants
- Variables
- func BuildHeaderMapping(headerRow []string, schema *Schema, opts MappingOptions) (map[int]int, error)
- func DefaultPositionalMapping(schema *Schema) map[int]int
- func IsEmptyRow(cells []string, trimSpace bool) bool
- type CellValidator
- type Column
- type ColumnMapping
- type ColumnSpec
- type ExportError
- type Exporter
- type Formatter
- type FormatterFunc
- type ImportError
- type Importer
- type MapOption
- type MappingOptions
- type ParseRowOptions
- type ParserFunc
- type RowAdapter
- type RowBuilder
- type RowReader
- type RowValidator
- type RowView
- type RowWriter
- type Schema
- type TypedExporter
- type TypedImporter
- type ValueParser
Constants ¶
const ( // TagTabular is the struct tag name for tabular field configuration. TagTabular = "tabular" // Tag attributes for field configuration. AttrDive = "dive" // Recursively parse embedded struct AttrName = "name" // Column name (header) AttrWidth = "width" // Column width (for display/export hints) AttrOrder = "order" // Column order AttrDefault = "default" // Default value for import AttrFormat = "format" // Format template (date/number format) AttrFormatter = "formatter" // Custom formatter name for export AttrParser = "parser" // Custom parser name for import // Special tag value. IgnoreField = "-" // Ignore this field )
Variables ¶
var ( // ErrUnsupportedType indicates the target type is not supported by the parser. ErrUnsupportedType = errors.New("unsupported type") // ErrDataMustBeSlice indicates the input data for export is not a slice. ErrDataMustBeSlice = errors.New("data must be a slice") // ErrNoDataRowsFound indicates the source contains no usable data rows. ErrNoDataRowsFound = errors.New("no data rows found") // ErrDuplicateColumnKey indicates a duplicate Key in a []ColumnSpec. ErrDuplicateColumnKey = errors.New("duplicate column key") // ErrDuplicateHeaderName indicates a duplicate header name during mapping. ErrDuplicateHeaderName = errors.New("duplicate header name") // ErrUnsetField indicates a struct field cannot be set (usually unexported). ErrUnsetField = errors.New("field is not settable") // ErrRequiredMissing indicates a required cell is empty. ErrRequiredMissing = errors.New("required value is missing") // ErrUnknownColumn indicates a column key is not present in the schema. ErrUnknownColumn = errors.New("unknown column") // ErrSchemaMismatch indicates the provided data does not match the schema // required by the adapter (e.g. wrong element type). ErrSchemaMismatch = errors.New("schema mismatch") // ErrMissingColumnType indicates a dynamic column spec has no target Type. ErrMissingColumnType = errors.New("column type is required") // ErrMissingColumnKey indicates a dynamic column spec has no Key. ErrMissingColumnKey = errors.New("column key is required") // ErrTypedRowMismatch indicates a TypedImporter received rows whose element // type does not match the requested generic parameter. ErrTypedRowMismatch = errors.New("importer returned unexpected row type") )
Functions ¶
func BuildHeaderMapping ¶ added in v0.22.0
func BuildHeaderMapping( headerRow []string, schema *Schema, opts MappingOptions, ) (map[int]int, error)
BuildHeaderMapping resolves a header row against the schema and returns a map from source column index to schema column index. Unknown headers are skipped; duplicate non-empty headers produce ErrDuplicateHeaderName.
func DefaultPositionalMapping ¶ added in v0.22.0
DefaultPositionalMapping returns a 1:1 index mapping suitable when the source has no header row.
func IsEmptyRow ¶ added in v0.22.0
IsEmptyRow reports whether every cell in the row is empty. When trimSpace is true, surrounding whitespace is ignored.
Types ¶
type CellValidator ¶ added in v0.22.0
CellValidator validates a single cell value within the context of a column. It is primarily used by dynamic (map-based) schemas; struct schemas typically rely on the standard `validate` tag via the framework validator.
type Column ¶
type Column struct {
// Key is the logical identifier of the column. For struct schemas it is the
// field name; for dynamic schemas it is the map key that addresses the cell.
Key string
// Name is the header text that appears in the exported file and is matched
// against the header row during import. Defaults to Key when empty.
Name string
// Type is the target Go type used when parsing cell values. For struct
// schemas it is derived from the struct field type; for dynamic schemas it
// must be provided via ColumnSpec.
Type reflect.Type
// Order controls the column order. Columns are sorted stably by Order.
Order int
// Width hints the column width for formats that support it (Excel).
Width float64
// Default is the value used during import when the source cell is empty.
Default string
// Format is the format template consumed by the default Formatter/Parser,
// e.g. "2006-01-02" for dates or "%.2f" for floats.
Format string
// Formatter is the name of a custom Formatter registered on the exporter.
Formatter string
// Parser is the name of a custom ValueParser registered on the importer.
Parser string
// FormatterFn is a Formatter instance bound directly on the column, taking
// precedence over the named Formatter registry.
FormatterFn Formatter
// ParserFn is a ValueParser instance bound directly on the column, taking
// precedence over the named ValueParser registry.
ParserFn ValueParser
// Required marks the column as mandatory; empty cells trigger a validation
// error during import. Applies to dynamic schemas.
Required bool
// Validators is an ordered list of custom cell validators. Applies to
// dynamic schemas.
Validators []CellValidator
// Index is the struct field index path used by StructAdapter. nil for
// dynamic columns.
Index []int
}
Column represents metadata for a single column in tabular data. Columns are shared between struct-based and dynamic schemas.
External code should construct Column instances through schema factories (NewSchema, NewSchemaFor, NewSchemaFromSpecs); fields are exported so that adapters can populate them, not for direct mutation by callers.
type ColumnMapping ¶ added in v0.22.0
type ColumnMapping struct {
// contains filtered or unexported fields
}
ColumnMapping holds a header-to-schema index mapping together with a pre-sorted key list so that ParseRow does not re-sort on every row.
func NewColumnMapping ¶ added in v0.22.0
func NewColumnMapping(m map[int]int) ColumnMapping
NewColumnMapping creates a ColumnMapping from a raw map, sorting the source indices once at construction time.
type ColumnSpec ¶ added in v0.22.0
type ColumnSpec struct {
// Key is the logical identifier and the map key used to read/write cell
// values. Required and must be unique within the schema.
Key string
// Name is the header text. Defaults to Key when empty.
Name string
// Type is the Go target type used for parsing. Required.
Type reflect.Type
// Order controls the column order; columns are sorted stably.
Order int
// Width hints the column width for Excel export.
Width float64
// Default is used during import when the cell is empty.
Default string
// Format template consumed by the default Formatter/Parser.
Format string
// Formatter / Parser names resolved against the exporter / importer
// registries.
Formatter string
Parser string
// FormatterFn / ParserFn bind implementations directly; they take
// precedence over the named lookups.
FormatterFn Formatter
ParserFn ValueParser
// Required marks the column as mandatory during import.
Required bool
// Validators runs additional cell validation after parsing.
Validators []CellValidator
}
ColumnSpec describes a dynamic column at runtime. It is converted to a Column by NewSchemaFromSpecs.
type ExportError ¶
ExportError represents an error that occurred during data export. Row is 0-based data row index.
func (ExportError) Error ¶
func (e ExportError) Error() string
Error implements the error interface.
func (ExportError) Unwrap ¶
func (e ExportError) Unwrap() error
Unwrap returns the underlying error.
type Exporter ¶
type Exporter interface {
// RegisterFormatter registers a custom formatter referenced by Column.Formatter.
RegisterFormatter(name string, formatter Formatter)
// ExportToFile exports data to a tabular file on disk.
ExportToFile(data any, filename string) error
// Export exports data to a bytes.Buffer carrying tabular content.
Export(data any) (*bytes.Buffer, error)
}
Exporter writes a slice of rows (struct or map) to a tabular destination (CSV, Excel, ...) Using a RowAdapter to read from the input.
type Formatter ¶
type Formatter interface {
// Format converts a Go value to a cell string
Format(value any) (string, error)
}
Formatter defines the interface for custom value formatters. Formatters convert Go values to cell strings during export.
func NewDefaultFormatter ¶
NewDefaultFormatter creates a default formatter with optional format template.
func ResolveFormatter ¶ added in v0.22.0
ResolveFormatter selects the Formatter to use for a column.
Precedence:
- Column.FormatterFn (direct instance override)
- Column.Formatter (name lookup in registry)
- NewDefaultFormatter(Column.Format)
If the name is set but not present in the registry, it is logged and the default formatter is returned so exports keep working.
type FormatterFunc ¶ added in v0.22.0
FormatterFunc adapts a plain function to the Formatter interface.
type ImportError ¶
ImportError represents an error that occurred during data import. Row is 1-based and includes the header row.
Err may carry multiple leaf errors joined via errors.Join when a single row produces several failures (e.g. multiple Required misses or both a cell validator and a row validator failing). Use errors.Is on the ImportError to match a specific cause; to enumerate all leaves, assert Err against the interface{ Unwrap() []error } interface.
func ParseRow ¶ added in v0.22.0
func ParseRow( cells []string, mapping ColumnMapping, schema *Schema, builder RowBuilder, parsers map[string]ValueParser, rowNumber int, opts ParseRowOptions, ) []ImportError
ParseRow walks a single source row and writes parsed cells into the row builder. The mapping translates source column index to schema column index. Cells are read in sorted source-index order so that per-row import errors are deterministic.
RowNumber is the human-facing row number (1-based, including the header row) used when constructing ImportError entries. Empty cells fall back to the column Default; cells that remain empty are skipped so that adapters (e.g. MapAdapter) can distinguish absent values from explicit zeroes and enforce Required.
When the returned slice is non-empty the row builder is in a partial state and should NOT be committed. Callers should skip Commit and collect the errors instead.
func (ImportError) Error ¶
func (e ImportError) Error() string
Error implements the error interface.
func (ImportError) Unwrap ¶
func (e ImportError) Unwrap() error
Unwrap returns the underlying error.
type Importer ¶
type Importer interface {
// RegisterParser registers a custom parser referenced by Column.Parser.
RegisterParser(name string, parser ValueParser)
// ImportFromFile imports data from a tabular file on disk.
ImportFromFile(filename string) (any, []ImportError, error)
// Import imports data from an io.Reader carrying tabular content.
Import(reader io.Reader) (any, []ImportError, error)
}
Importer reads tabular data (CSV, Excel, ...) Into a slice of rows produced by a RowAdapter. The shape of the returned data depends on the adapter: struct adapters return []T, map adapters return []map[string]any.
type MapOption ¶ added in v0.22.0
type MapOption func(*mapAdapter)
MapOption customizes MapAdapter behavior.
func WithRowValidator ¶ added in v0.22.0
func WithRowValidator(validator RowValidator) MapOption
WithRowValidator registers a validator that runs after all cells have been populated for a map-shaped row.
type MappingOptions ¶ added in v0.22.0
type MappingOptions struct {
// TrimSpace trims leading/trailing whitespace from each header cell.
TrimSpace bool
}
MappingOptions controls header-to-schema resolution.
type ParseRowOptions ¶ added in v0.22.0
type ParseRowOptions struct {
// TrimSpace strips leading/trailing whitespace from each source cell
// before applying defaults.
TrimSpace bool
}
ParseRowOptions controls cell-level normalization performed by ParseRow.
type ParserFunc ¶ added in v0.22.0
ParserFunc adapts a plain function to the ValueParser interface.
type RowAdapter ¶ added in v0.22.0
type RowAdapter interface {
// Schema returns the column definitions this adapter is built for.
Schema() *Schema
// Reader wraps the caller-provided data (e.g. []Struct, []map[string]any)
// into an iterable sequence of read-only row views for export.
Reader(data any) (RowReader, error)
// Writer creates a result accumulator used by importers. The capacity hint
// is advisory; adapters may ignore it.
Writer(capacity int) RowWriter
}
RowAdapter is the single bridge between the tabular engine (csv / excel importers and exporters) and any row model. Each adapter owns its Schema so callers only pass the adapter around; schema/model mismatches are impossible by construction.
func NewMapAdapter ¶ added in v0.22.0
func NewMapAdapter(schema *Schema, opts ...MapOption) RowAdapter
NewMapAdapter creates a RowAdapter driven by the supplied Schema. The schema is typically built from a []ColumnSpec via NewSchemaFromSpecs.
func NewMapAdapterFromSpecs ¶ added in v0.22.0
func NewMapAdapterFromSpecs(specs []ColumnSpec, opts ...MapOption) (RowAdapter, error)
NewMapAdapterFromSpecs is a convenience helper that turns dynamic column specs directly into a MapAdapter, applying any MapAdapter options.
func NewStructAdapter ¶ added in v0.22.0
func NewStructAdapter(typ reflect.Type) RowAdapter
NewStructAdapter creates a RowAdapter bound to the given struct type. Non-struct types produce a schema with no columns; the resulting adapter still satisfies the interface but Reader/Writer calls will return zero rows.
func NewStructAdapterFor ¶ added in v0.22.0
func NewStructAdapterFor[T any]() RowAdapter
NewStructAdapterFor creates a StructAdapter for the concrete type T.
type RowBuilder ¶ added in v0.22.0
type RowBuilder interface {
// Set writes a parsed value for the given column.
Set(column *Column, value any) error
// Validate runs adapter-specific validation hooks (e.g. struct validator
// or per-column cell validators plus row validators for maps).
Validate() error
// Value returns the underlying row representation (struct or map) in its
// current state.
Value() any
}
RowBuilder represents a single row under construction during import.
type RowReader ¶ added in v0.22.0
type RowReader interface {
// All yields 0-based row index and a RowView for each row.
All() iter.Seq2[int, RowView]
}
RowReader iterates over rows of export input.
type RowValidator ¶ added in v0.22.0
RowValidator validates a complete map-shaped row after all cells have been set. It is used by MapAdapter; struct schemas validate the whole struct instead.
type RowView ¶ added in v0.22.0
type RowView interface {
// Get returns the raw Go value held for the column. It may be nil for
// missing map keys or zero struct fields.
Get(column *Column) (any, error)
}
RowView exposes a read-only cell accessor for a single row.
type RowWriter ¶ added in v0.22.0
type RowWriter interface {
// NewRow creates a fresh, writable row builder.
NewRow() RowBuilder
// Commit validates and appends the given row to the result set.
Commit(row RowBuilder) error
// Build returns the final aggregated result (e.g. []T or []map[string]any).
Build() any
}
RowWriter accumulates imported rows and produces the final result.
type Schema ¶
type Schema struct {
// contains filtered or unexported fields
}
Schema contains the pre-parsed tabular metadata describing the columns of a tabular row model. It is produced either from a struct type or from a []ColumnSpec describing dynamic columns.
func NewSchemaFor ¶
NewSchemaFor creates a Schema instance from type T.
func NewSchemaFromSpecs ¶ added in v0.22.0
func NewSchemaFromSpecs(specs []ColumnSpec) (*Schema, error)
NewSchemaFromSpecs builds a Schema from a slice of dynamic column specs. It validates that every spec has a non-empty Key and Type, and that keys and resolved names are unique.
func (*Schema) ColumnByKey ¶ added in v0.22.0
ColumnByKey returns the column addressed by the given logical key.
func (*Schema) ColumnByName ¶ added in v0.22.0
ColumnByName returns the column with the given header name.
func (*Schema) ColumnCount ¶
ColumnCount returns the number of columns.
func (*Schema) ColumnNames ¶
ColumnNames returns all column header names.
type TypedExporter ¶ added in v0.22.0
type TypedExporter[T any] struct { // contains filtered or unexported fields }
TypedExporter wraps an Exporter to accept strongly-typed []T input, keeping export call sites free of any-typed values.
func NewTypedExporter ¶ added in v0.22.0
func NewTypedExporter[T any](inner Exporter) TypedExporter[T]
NewTypedExporter wraps an existing Exporter with strongly-typed input.
func (TypedExporter[T]) Export ¶ added in v0.22.0
func (e TypedExporter[T]) Export(rows []T) (*bytes.Buffer, error)
Export exports rows to an in-memory buffer.
func (TypedExporter[T]) ExportToFile ¶ added in v0.22.0
func (e TypedExporter[T]) ExportToFile(rows []T, filename string) error
ExportToFile exports rows to a file on disk.
func (TypedExporter[T]) Inner ¶ added in v0.22.0
func (e TypedExporter[T]) Inner() Exporter
Inner returns the underlying untyped exporter for advanced usage such as registering custom formatters without going through the typed wrapper.
func (TypedExporter[T]) RegisterFormatter ¶ added in v0.22.0
func (e TypedExporter[T]) RegisterFormatter(name string, formatter Formatter)
RegisterFormatter delegates to the underlying exporter.
type TypedImporter ¶ added in v0.22.0
type TypedImporter[T any] struct { // contains filtered or unexported fields }
TypedImporter wraps an Importer to return strongly-typed []T results, removing the need for callers to perform a type assertion on each call. It is intended for struct-backed adapters; map adapters return []map[string]any and should keep using the untyped Importer.
func NewTypedImporter ¶ added in v0.22.0
func NewTypedImporter[T any](inner Importer) TypedImporter[T]
NewTypedImporter wraps an existing Importer with strongly-typed result access. The underlying importer must produce []T values; otherwise Import and ImportFromFile will return a type-mismatch error at call time.
func (TypedImporter[T]) Import ¶ added in v0.22.0
func (i TypedImporter[T]) Import(reader io.Reader) ([]T, []ImportError, error)
Import imports rows from reader and returns them as []T.
func (TypedImporter[T]) ImportFromFile ¶ added in v0.22.0
func (i TypedImporter[T]) ImportFromFile(filename string) ([]T, []ImportError, error)
ImportFromFile imports rows from disk and returns them as []T.
func (TypedImporter[T]) Inner ¶ added in v0.22.0
func (i TypedImporter[T]) Inner() Importer
Inner returns the underlying untyped importer for advanced usage such as registering custom parsers without going through the typed wrapper.
func (TypedImporter[T]) RegisterParser ¶ added in v0.22.0
func (i TypedImporter[T]) RegisterParser(name string, parser ValueParser)
RegisterParser delegates to the underlying importer.
type ValueParser ¶
type ValueParser interface {
// Parse converts a cell string to a Go value
Parse(cellValue string, targetType reflect.Type) (any, error)
}
ValueParser defines the interface for custom value parsers. Parsers convert cell strings to Go values during import.
func NewDefaultParser ¶
func NewDefaultParser(format string) ValueParser
NewDefaultParser creates a default parser with optional format template.
func ResolveParser ¶ added in v0.22.0
func ResolveParser(col *Column, registry map[string]ValueParser) ValueParser
ResolveParser selects the ValueParser to use for a column using the same precedence rules as ResolveFormatter.