Skip to content

Latest commit

 

History

History
71 lines (60 loc) · 1.74 KB

File metadata and controls

71 lines (60 loc) · 1.74 KB

csvheaders

Manipulate CSV headers while parsing files

Motivation

I have faced many CSV files representing the same data, or having to be unmarshalled to the same structures, but always with a twist on the headers.

Sometimes, the headers didn't have the proper case. Sometimes, they were just plain wrong. Sometimes, whoever generated the file forgot to trim them.

Unfortunately, Go's csv:"..." tag is very strict. Take the following example, a CSV file provided by a French company:

Nom,Numéro
John,0123456789
Anna,0987654321

Unmarshalling this to the following struct in Go is tedious:

type Person struct {
	Name        string `csv:"NAME"`
	PhoneNumber string `csv:"PHONE NUMBER"`
}

It's tedious because the csv:"Phone" tag doesn´t match the header Numéro.

The goal of this library is to make processing of CSV files with "variable" headers simpler.

Usage

In order to use this library, one needs to have a csv.Reader already.

The next requirement is to have a list of the header mappings, as a map. These go from the file to the struct. In our example above, the header replacemenent would be:

headerReplacements := map[string]string{
	"Nom":    "NAME",
	"Numéro": "PHONE NUMBER",
}

Finally, we can build a replacer with:

replacer := csvheaders.NewReplacer(csvReader, headerReplacements)

This replacer can be fed to csv parsing libraries such as gocsv or goflat:

file, err := os.Open("phone_directory.csv")
if err != nil {
	...
}
defer file.Close()

csvReader := csvheaders.NewReplacer(
	csv.NewReader(file),
	map[string]string{
        "Nom": "NAME",
        "Numéro": "PHONE NUMBER",
    })

var rows []*Person
err := gocsv.UnmarshalCSV(csvReader, &rows)
if err != nil {
	...
}