Skip to content

Commit 4dd9054

Browse files
committed
Strip the byte-order mark at the start of the JSON string
1 parent d790852 commit 4dd9054

File tree

2 files changed

+24
-4
lines changed

2 files changed

+24
-4
lines changed

index.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,12 @@ class JSONParseError extends SyntaxError {
5353
}
5454

5555
const parseJson = (txt, reviver, context) => {
56+
const parseText = stripBOM(txt)
5657
context = context || 20
5758
try {
58-
return JSON.parse(txt, reviver)
59+
return JSON.parse(parseText, reviver)
5960
} catch (e) {
60-
if (typeof txt !== 'string') {
61+
if (typeof txt !== 'string' && !Buffer.isBuffer(txt)) {
6162
const isEmptyArray = Array.isArray(txt) && txt.length === 0
6263
throw Object.assign(new TypeError(
6364
`Cannot parse ${isEmptyArray ? 'an empty array' : String(txt)}`
@@ -67,9 +68,14 @@ const parseJson = (txt, reviver, context) => {
6768
})
6869
}
6970

70-
throw new JSONParseError(e, txt, context, parseJson)
71+
throw new JSONParseError(e, parseText, context, parseJson)
7172
}
7273
}
7374

75+
// Remove byte order marker. This catches EF BB BF (the UTF-8 BOM)
76+
// because the buffer-to-string conversion in `fs.readFileSync()`
77+
// translates it to FEFF, the UTF-16 BOM.
78+
const stripBOM = txt => String(txt).replace(/^\uFEFF/, '')
79+
7480
module.exports = parseJson
7581
parseJson.JSONParseError = JSONParseError

test/index.js

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,24 @@ t.test('parses JSON', t => {
1111
baz: [1, 2, 3, 'four']
1212
}
1313
})
14-
t.deepEqual(JSON.parse(data), parseJson(data), 'does the same thing')
14+
t.deepEqual(parseJson(data), JSON.parse(data), 'does the same thing')
1515
t.done()
1616
})
1717

18+
t.test('parses JSON if it is a Buffer, removing BOM bytes', t => {
19+
const str = JSON.stringify({
20+
foo: 1,
21+
bar: {
22+
baz: [1, 2, 3, 'four']
23+
}
24+
})
25+
const data = Buffer.from(str)
26+
const bom = Buffer.concat([Buffer.from([0xEF, 0xBB, 0xBF]), data])
27+
t.deepEqual(parseJson(data), JSON.parse(str))
28+
t.deepEqual(parseJson(bom), JSON.parse(str), 'strips the byte order marker')
29+
t.end()
30+
})
31+
1832
t.test('throws SyntaxError for unexpected token', t => {
1933
const data = 'foo'
2034
t.throws(

0 commit comments

Comments
 (0)