From 3195e0686ca9faeac710d056779795d3e2bb277c Mon Sep 17 00:00:00 2001 From: Dylan Hall Date: Mon, 15 Jun 2026 13:30:01 +1000 Subject: [PATCH 1/2] fix issue reading files with Byte Order Mark --- internal/jsonx/json.go | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/internal/jsonx/json.go b/internal/jsonx/json.go index 561d8c24..187b262f 100644 --- a/internal/jsonx/json.go +++ b/internal/jsonx/json.go @@ -35,9 +35,22 @@ func Parse(b []byte) (*Node, error) { } func NewJsonParser(rd io.Reader, strict bool) *JsonParser { + // Read up to the first 3 bytes to check for a BOM + header := make([]byte, 3) + n, _ := io.ReadFull(rd, header) // We ignore the error; if the file is < 3 bytes, n handles it + + // Get stream to read + var finalReader io.Reader + if n == 3 && header[0] == '\xef' && header[1] == '\xbb' && header[2] == '\xbf' { + // It IS a BOM! throw the header away and proceed with the remaining stream + finalReader = rd + } else { + // Not a BOM - stitch the bytes we just read back onto the front of the stream + finalReader = io.MultiReader(bytes.NewReader(header[:n]), rd) + } p := &JsonParser{ strict: strict, - rd: rd, + rd: finalReader, buf: make([]byte, 4096), lineNumber: 1, realLineNumber: 1, From d3cf5a4d70796896916558df3855a414b6434508 Mon Sep 17 00:00:00 2001 From: Dylan Hall Date: Mon, 15 Jun 2026 13:47:06 +1000 Subject: [PATCH 2/2] simplify the fix a little --- internal/jsonx/json.go | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/internal/jsonx/json.go b/internal/jsonx/json.go index 187b262f..7f3f2348 100644 --- a/internal/jsonx/json.go +++ b/internal/jsonx/json.go @@ -39,18 +39,14 @@ func NewJsonParser(rd io.Reader, strict bool) *JsonParser { header := make([]byte, 3) n, _ := io.ReadFull(rd, header) // We ignore the error; if the file is < 3 bytes, n handles it - // Get stream to read - var finalReader io.Reader - if n == 3 && header[0] == '\xef' && header[1] == '\xbb' && header[2] == '\xbf' { - // It IS a BOM! throw the header away and proceed with the remaining stream - finalReader = rd - } else { - // Not a BOM - stitch the bytes we just read back onto the front of the stream - finalReader = io.MultiReader(bytes.NewReader(header[:n]), rd) + // Replace stream with stitched stream if BOM isn't detected + if n != 3 || header[0] != '\xef' || header[1] != '\xbb' || header[2] != '\xbf' { + rd = io.MultiReader(bytes.NewReader(header[:n]), rd) } + p := &JsonParser{ strict: strict, - rd: finalReader, + rd: rd, buf: make([]byte, 4096), lineNumber: 1, realLineNumber: 1,