package main import ( "bytes" "encoding/csv" "encoding/json" "fmt" "io" "log" "os" "strconv" "strings" ) type replacer struct { r io.Reader } func (r replacer) Read(b []byte) (int, error) { n, err := r.r.Read(b) c := bytes.ReplaceAll(b[:n], []byte("\r"), []byte("\n")) c = bytes.ReplaceAll(c, []byte(`,="`), []byte(`,"`)) copy(b, c) return len(c), err } func main() { parser := csv.NewReader(replacer{os.Stdin}) fields, err := parser.Read() if err != nil { panic(err) } for i := range fields { fields[i] = strings.TrimSpace(fields[i]) } n := 0 for { n += 1 line, err := parser.Read() if err == io.EOF { break } if err != nil && !strings.Contains(err.Error(), "wrong number of fields") { panic(err) } for len(line) < len(fields) { line = append(line, "null") } if len(line) != len(fields) { log.Println("[WARN]", "line", n, "has", len(line), "fields but only", len(fields), "are known") } lineResult := map[string]string{} for i := range line { k := strconv.Itoa(i) if i < len(fields) { k = fields[i] } lineResult[k] = line[i] } b, _ := json.Marshal(lineResult) fmt.Printf("%s\n", b) } }