package jsonstream import ( "bytes" "encoding/json" "fmt" "sort" ) // FormatType denotes the output formatting types supported by jsonstream type FormatType int const ( // FormatJSON informs the Formatter to output as a JSON object FormatJSON FormatType = iota // FormatTSV informs the Formatter to output as a tab separated JSON encoded values FormatTSV // FormatTSVKey informs the Formatter to output as a tab separated `=` pairs FormatTSVKey ) // Formatter is used for formatting any data into a byte slice type Formatter struct { format FormatType } // NewFormatter will create a new Formatter with the designated output format func NewFormatter(format FormatType) *Formatter { return &Formatter{ format: format, } } // Format the provided data into the output format designated for this Formatter func (formatter *Formatter) Format(data interface{}) (buf []byte, err error) { if formatter.format == FormatJSON { buf, err = formatter.formatJSON(data) } else if formatter.format == FormatTSV { buf, err = formatter.formatTSV(data, false) } else if formatter.format == FormatTSVKey { buf, err = formatter.formatTSV(data, true) } else { err = fmt.Errorf("Unknown FormatType '%v+'. Options are FormatJSON=0, or FormatTSV=1", formatter.format) } return buf, err } func (formatter *Formatter) formatJSON(data interface{}) (buf []byte, err error) { return json.Marshal(data) } func (formatter *Formatter) formatTSV(data interface{}, keyed bool) (buf []byte, err error) { var fields map[string]interface{} fields, err = getAsMap(data) if err != nil { return buf, err } var values [][]byte var keys []string for key := range fields { keys = append(keys, key) } sort.Strings(keys) for _, key := range keys { var value []byte value, err = formatter.formatJSON(fields[key]) if err != nil { break } if keyed { value = []byte(fmt.Sprintf("%s=%s", key, value)) } values = append(values, value) } buf = bytes.Join(values, []byte{'\t'}) return buf, err }