fast-json-stringify 6.1.0 → 6.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/serializer.js +4 -1
- package/package.json +1 -1
- package/test/issue-793.test.js +107 -0
- package/test/issue-794.test.js +177 -0
package/lib/serializer.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
// eslint-disable-next-line
|
|
4
|
+
const STR_ESCAPE = /[\u0000-\u001f\u0022\u005c\ud800-\udfff]/
|
|
5
|
+
|
|
3
6
|
module.exports = class Serializer {
|
|
4
7
|
constructor (options) {
|
|
5
8
|
switch (options && options.rounding) {
|
|
@@ -116,7 +119,7 @@ module.exports = class Serializer {
|
|
|
116
119
|
}
|
|
117
120
|
}
|
|
118
121
|
return (last === -1 && ('"' + str + '"')) || ('"' + result + str.slice(last) + '"')
|
|
119
|
-
} else if (len < 5000 &&
|
|
122
|
+
} else if (len < 5000 && STR_ESCAPE.test(str) === false) {
|
|
120
123
|
// Only use the regular expression for shorter input. The overhead is otherwise too much.
|
|
121
124
|
return '"' + str + '"'
|
|
122
125
|
} else {
|
package/package.json
CHANGED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { test } = require('node:test')
|
|
4
|
+
|
|
5
|
+
const build = require('..')
|
|
6
|
+
|
|
7
|
+
test('serialize string with newlines - issue #793', (t) => {
|
|
8
|
+
t.plan(2)
|
|
9
|
+
|
|
10
|
+
const schema = {
|
|
11
|
+
type: 'object',
|
|
12
|
+
properties: {
|
|
13
|
+
message: {
|
|
14
|
+
type: 'string'
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const input = {
|
|
20
|
+
message: `This is a string
|
|
21
|
+
with multiple
|
|
22
|
+
newlines in it
|
|
23
|
+
Foo`
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const stringify = build(schema)
|
|
27
|
+
const output = stringify(input)
|
|
28
|
+
|
|
29
|
+
// The output should be valid JSON
|
|
30
|
+
t.assert.doesNotThrow(() => {
|
|
31
|
+
JSON.parse(output)
|
|
32
|
+
}, 'JSON output should be parseable')
|
|
33
|
+
|
|
34
|
+
// The parsed output should match the input
|
|
35
|
+
const parsed = JSON.parse(output)
|
|
36
|
+
t.assert.equal(parsed.message, input.message)
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
test('serialize string with various newline characters - issue #793', (t) => {
|
|
40
|
+
t.plan(4)
|
|
41
|
+
|
|
42
|
+
const schema = {
|
|
43
|
+
type: 'string'
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const stringify = build(schema)
|
|
47
|
+
|
|
48
|
+
// Test \n (line feed)
|
|
49
|
+
const inputLF = 'line1\nline2'
|
|
50
|
+
const outputLF = stringify(inputLF)
|
|
51
|
+
t.assert.equal(JSON.parse(outputLF), inputLF)
|
|
52
|
+
|
|
53
|
+
// Test \r (carriage return)
|
|
54
|
+
const inputCR = 'line1\rline2'
|
|
55
|
+
const outputCR = stringify(inputCR)
|
|
56
|
+
t.assert.equal(JSON.parse(outputCR), inputCR)
|
|
57
|
+
|
|
58
|
+
// Test \r\n (CRLF)
|
|
59
|
+
const inputCRLF = 'line1\r\nline2'
|
|
60
|
+
const outputCRLF = stringify(inputCRLF)
|
|
61
|
+
t.assert.equal(JSON.parse(outputCRLF), inputCRLF)
|
|
62
|
+
|
|
63
|
+
// Test mixed newlines
|
|
64
|
+
const inputMixed = 'line1\nline2\rline3\r\nline4'
|
|
65
|
+
const outputMixed = stringify(inputMixed)
|
|
66
|
+
t.assert.equal(JSON.parse(outputMixed), inputMixed)
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
test('serialize object with newlines in multiple properties - issue #793', (t) => {
|
|
70
|
+
t.plan(2)
|
|
71
|
+
|
|
72
|
+
const schema = {
|
|
73
|
+
type: 'object',
|
|
74
|
+
properties: {
|
|
75
|
+
message: {
|
|
76
|
+
type: 'string'
|
|
77
|
+
},
|
|
78
|
+
description: {
|
|
79
|
+
type: 'string'
|
|
80
|
+
},
|
|
81
|
+
timestamp: {
|
|
82
|
+
type: 'string'
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const input = {
|
|
88
|
+
message: `This is a string
|
|
89
|
+
with multiple
|
|
90
|
+
newlines in it
|
|
91
|
+
Foo`,
|
|
92
|
+
description: 'This JSON response contains a field with newline characters',
|
|
93
|
+
timestamp: new Date().toISOString()
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const stringify = build(schema)
|
|
97
|
+
const output = stringify(input)
|
|
98
|
+
|
|
99
|
+
// The output should be valid JSON
|
|
100
|
+
t.assert.doesNotThrow(() => {
|
|
101
|
+
JSON.parse(output)
|
|
102
|
+
}, 'JSON output should be parseable')
|
|
103
|
+
|
|
104
|
+
// The parsed output should match the input
|
|
105
|
+
const parsed = JSON.parse(output)
|
|
106
|
+
t.assert.deepEqual(parsed, input)
|
|
107
|
+
})
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { test } = require('node:test')
|
|
4
|
+
|
|
5
|
+
const build = require('..')
|
|
6
|
+
|
|
7
|
+
test('serialize string with quotes - issue #794', (t) => {
|
|
8
|
+
t.plan(2)
|
|
9
|
+
|
|
10
|
+
const schema = {
|
|
11
|
+
type: 'object',
|
|
12
|
+
properties: {
|
|
13
|
+
message: {
|
|
14
|
+
type: 'string'
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const input = {
|
|
20
|
+
message: 'Error: Property "name" is required'
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const stringify = build(schema)
|
|
24
|
+
const output = stringify(input)
|
|
25
|
+
|
|
26
|
+
// The output should be valid JSON
|
|
27
|
+
t.assert.doesNotThrow(() => {
|
|
28
|
+
JSON.parse(output)
|
|
29
|
+
}, 'JSON output should be parseable')
|
|
30
|
+
|
|
31
|
+
// The parsed output should match the input
|
|
32
|
+
const parsed = JSON.parse(output)
|
|
33
|
+
t.assert.equal(parsed.message, input.message)
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
test('serialize string with various quote types - issue #794', (t) => {
|
|
37
|
+
t.plan(6)
|
|
38
|
+
|
|
39
|
+
const schema = {
|
|
40
|
+
type: 'string'
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const stringify = build(schema)
|
|
44
|
+
|
|
45
|
+
// Test double quotes
|
|
46
|
+
const inputDoubleQuotes = 'Property "name" is required'
|
|
47
|
+
const outputDoubleQuotes = stringify(inputDoubleQuotes)
|
|
48
|
+
t.assert.doesNotThrow(() => JSON.parse(outputDoubleQuotes))
|
|
49
|
+
t.assert.equal(JSON.parse(outputDoubleQuotes), inputDoubleQuotes)
|
|
50
|
+
|
|
51
|
+
// Test single quotes (should be fine but test for completeness)
|
|
52
|
+
const inputSingleQuotes = "Property 'name' is required"
|
|
53
|
+
const outputSingleQuotes = stringify(inputSingleQuotes)
|
|
54
|
+
t.assert.doesNotThrow(() => JSON.parse(outputSingleQuotes))
|
|
55
|
+
t.assert.equal(JSON.parse(outputSingleQuotes), inputSingleQuotes)
|
|
56
|
+
|
|
57
|
+
// Test mixed quotes
|
|
58
|
+
const inputMixedQuotes = 'Error: "Property \'name\' is required"'
|
|
59
|
+
const outputMixedQuotes = stringify(inputMixedQuotes)
|
|
60
|
+
t.assert.doesNotThrow(() => JSON.parse(outputMixedQuotes))
|
|
61
|
+
t.assert.equal(JSON.parse(outputMixedQuotes), inputMixedQuotes)
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
test('serialize error-like object with quotes in message - issue #794', (t) => {
|
|
65
|
+
t.plan(2)
|
|
66
|
+
|
|
67
|
+
const schema = {
|
|
68
|
+
type: 'object',
|
|
69
|
+
properties: {
|
|
70
|
+
error: {
|
|
71
|
+
type: 'object',
|
|
72
|
+
properties: {
|
|
73
|
+
message: {
|
|
74
|
+
type: 'string'
|
|
75
|
+
},
|
|
76
|
+
code: {
|
|
77
|
+
type: 'string'
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const input = {
|
|
85
|
+
error: {
|
|
86
|
+
message: 'Validation failed: Property "email" must be a valid email address',
|
|
87
|
+
code: 'VALIDATION_ERROR'
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const stringify = build(schema)
|
|
92
|
+
const output = stringify(input)
|
|
93
|
+
|
|
94
|
+
// The output should be valid JSON
|
|
95
|
+
t.assert.doesNotThrow(() => {
|
|
96
|
+
JSON.parse(output)
|
|
97
|
+
}, 'JSON output should be parseable')
|
|
98
|
+
|
|
99
|
+
// The parsed output should match the input
|
|
100
|
+
const parsed = JSON.parse(output)
|
|
101
|
+
t.assert.deepEqual(parsed, input)
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
test('serialize validation errors array with quotes - issue #794', (t) => {
|
|
105
|
+
t.plan(2)
|
|
106
|
+
|
|
107
|
+
const schema = {
|
|
108
|
+
type: 'object',
|
|
109
|
+
properties: {
|
|
110
|
+
errors: {
|
|
111
|
+
type: 'array',
|
|
112
|
+
items: {
|
|
113
|
+
type: 'object',
|
|
114
|
+
properties: {
|
|
115
|
+
message: {
|
|
116
|
+
type: 'string'
|
|
117
|
+
},
|
|
118
|
+
field: {
|
|
119
|
+
type: 'string'
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const input = {
|
|
128
|
+
errors: [
|
|
129
|
+
{
|
|
130
|
+
message: 'Property "name" is required',
|
|
131
|
+
field: 'name'
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
message: 'Property "email" must be a valid email address',
|
|
135
|
+
field: 'email'
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
message: 'Value must be between "1" and "100"',
|
|
139
|
+
field: 'age'
|
|
140
|
+
}
|
|
141
|
+
]
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const stringify = build(schema)
|
|
145
|
+
const output = stringify(input)
|
|
146
|
+
|
|
147
|
+
// The output should be valid JSON
|
|
148
|
+
t.assert.doesNotThrow(() => {
|
|
149
|
+
JSON.parse(output)
|
|
150
|
+
}, 'JSON output should be parseable')
|
|
151
|
+
|
|
152
|
+
// The parsed output should match the input
|
|
153
|
+
const parsed = JSON.parse(output)
|
|
154
|
+
t.assert.deepEqual(parsed, input)
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
test('serialize string with backslashes and quotes - issue #794', (t) => {
|
|
158
|
+
t.plan(4)
|
|
159
|
+
|
|
160
|
+
const schema = {
|
|
161
|
+
type: 'string'
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const stringify = build(schema)
|
|
165
|
+
|
|
166
|
+
// Test backslashes
|
|
167
|
+
const inputBackslash = 'Path: C:\\Users\\test\\file.json'
|
|
168
|
+
const outputBackslash = stringify(inputBackslash)
|
|
169
|
+
t.assert.doesNotThrow(() => JSON.parse(outputBackslash))
|
|
170
|
+
t.assert.equal(JSON.parse(outputBackslash), inputBackslash)
|
|
171
|
+
|
|
172
|
+
// Test combination of backslashes and quotes
|
|
173
|
+
const inputMixed = 'Error: Could not find file "C:\\Users\\test\\config.json"'
|
|
174
|
+
const outputMixed = stringify(inputMixed)
|
|
175
|
+
t.assert.doesNotThrow(() => JSON.parse(outputMixed))
|
|
176
|
+
t.assert.equal(JSON.parse(outputMixed), inputMixed)
|
|
177
|
+
})
|