handle input json in formats other than utf8
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2024-10-09 08:53:44 +11:00
parent c144f1c8bf
commit 5886175f8a

72
main.go
View File

@@ -1,6 +1,7 @@
package main
import (
"bytes"
"encoding/json"
"flag"
"fmt"
@@ -15,6 +16,9 @@ import (
"time"
"github.com/xuri/excelize/v2"
"golang.org/x/text/encoding/unicode"
"golang.org/x/text/transform"
"golang.org/x/text/unicode/norm"
)
type Input struct {
@@ -232,7 +236,7 @@ func AvgChart(f *excelize.File, worksheetName string, location string, avgCpuCol
chartSeries = append(chartSeries, thisChartSeries)
}
if err := f.AddChart("Report", location, &excelize.Chart{
chart := excelize.Chart{
Type: excelize.Line,
Series: chartSeries,
Format: excelize.GraphicOptions{
@@ -278,14 +282,19 @@ func AvgChart(f *excelize.File, worksheetName string, location string, avgCpuCol
Font: excelize.Font{
Color: "000000",
},
Maximum: &yMaxValue,
Minimum: &yMinValue,
},
Dimension: excelize.ChartDimension{
Height: 500,
Width: 800,
},
}); err != nil {
}
if yMaxValue > 0 || yMinValue > 0 {
chart.YAxis.Maximum = &yMaxValue
chart.YAxis.Minimum = &yMinValue
}
if err := f.AddChart("Report", location, &chart); err != nil {
fmt.Printf("Error adding chart to workbook %s at location %s: %s\n", worksheetName, location, err)
return
}
@@ -293,6 +302,7 @@ func AvgChart(f *excelize.File, worksheetName string, location string, avgCpuCol
func main() {
var err error
var data Input
inputFile := flag.String("input", "input.json", "The filename from which to load historical data")
outputFile := flag.String("output", "book1.xlsx", "The filename to use when writing excel workbook")
@@ -322,9 +332,19 @@ func main() {
}
defer file.Close()
byteValue, _ := io.ReadAll(file)
var data Input
if err := json.Unmarshal(byteValue, &data); err != nil {
byteValue, err := io.ReadAll(file)
if err != nil {
log.Fatalf("Failed to read input json: %v", err)
}
// Detect encoding and convert to UTF-8 if necessary
utf8Data, err := ensureUTF8(byteValue)
if err != nil {
fmt.Printf("Error ensuring UTF-8 encoding: %v\n", err)
return
}
if err := json.Unmarshal(utf8Data, &data); err != nil {
fmt.Printf("Error reading json input: %s\n", err)
os.Exit(1)
}
@@ -366,6 +386,44 @@ func sortDates(dates []string) error {
return nil
}
// ensureUTF8 checks if the data is UTF-8, and if not, converts it to UTF-8.
// It also removes BOM from UTF-8 if present.
func ensureUTF8(data []byte) ([]byte, error) {
// Detect and strip UTF-8 BOM if present
if hasUTF8BOM(data) {
data = stripUTF8BOM(data)
}
// If data is already UTF-8 (without BOM), return as is
if isUTF8(data) {
return data, nil
}
// Detect and decode UTF-16 (either UTF-16LE or UTF-16BE)
decoder := unicode.UTF16(unicode.LittleEndian, unicode.UseBOM).NewDecoder()
utf8Data, _, err := transform.Bytes(decoder, data)
if err != nil {
return nil, fmt.Errorf("error converting to UTF-8: %v", err)
}
return utf8Data, nil
}
// isUTF8 checks if the byte slice is already encoded in UTF-8
func isUTF8(data []byte) bool {
return bytes.Equal(data, norm.NFC.Bytes(data)) // UTF-8 normalization check
}
// hasUTF8BOM checks if the data has a UTF-8 BOM
func hasUTF8BOM(data []byte) bool {
return len(data) >= 3 && data[0] == 0xEF && data[1] == 0xBB && data[2] == 0xBF
}
// stripUTF8BOM removes the UTF-8 BOM if it exists
func stripUTF8BOM(data []byte) []byte {
return data[3:]
}
func fetchValue(value interface{}) {
switch value.(type) {
case string: