Skip to content

Commit

Permalink
feat: #127 skip ellipsis in arrays and objects
Browse files Browse the repository at this point in the history
  • Loading branch information
josdejong committed May 15, 2024
1 parent e778b5e commit 019e509
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 1 deletion.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ The following issues can be fixed:
- Replace Python constants `None`, `True`, and `False` with `null`, `true`, and `false`
- Strip trailing commas
- Strip comments like `/* ... */` and `// ...`
- Strip ellipsis in arrays and objects like `[1, 2, 3, ...]`
- Strip JSONP notation like `callback({ ... })`
- Strip escape characters from an escaped string like `{\"stringified\": \"content\"}`
- Strip MongoDB data types like `NumberLong(2)` and `ISODate("2012-12-19T06:01:17.171Z")`
Expand Down
21 changes: 21 additions & 0 deletions src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,27 @@ describe.each(implementations)('jsonrepair [$name]', ({ jsonrepair }) => {
expect(jsonrepair('{"message": "with, multiple, commma\'s, you see?')).toBe('{"message": "with, multiple, commma\'s, you see?"}')
})

test('should repair ellipsis in an array', () => {
expect(jsonrepair('[1,2,3,...]')).toBe('[1,2,3]')
expect(jsonrepair('[1, 2, 3, ... ]')).toBe('[1, 2, 3 ]')
expect(jsonrepair('[1,2,3,/*comment1*/.../*comment2*/]')).toBe('[1,2,3]')
expect(jsonrepair('[\n 1,\n 2,\n 3,\n /*comment1*/ .../*comment2*/\n]')).toBe('[\n 1,\n 2,\n 3\n \n]')
expect(jsonrepair('{"array":[1,2,3,...]}')).toBe('{"array":[1,2,3]}')
expect(jsonrepair('[1,2,3,...,9]')).toBe('[1,2,3,9]')
expect(jsonrepair('[...,7,8,9]')).toBe('[7,8,9]')
expect(jsonrepair('[..., 7,8,9]')).toBe('[ 7,8,9]')
})

test('should repair ellipsis in an object', () => {
expect(jsonrepair('{"a":2,"b":3,...}')).toBe('{"a":2,"b":3}')
expect(jsonrepair('{"a":2,"b":3,/*comment1*/.../*comment2*/}')).toBe('{"a":2,"b":3}')
expect(jsonrepair('{\n "a":2,\n "b":3,\n /*comment1*/.../*comment2*/\n}')).toBe('{\n "a":2,\n "b":3\n \n}')
expect(jsonrepair('{"a":2,"b":3, ... }')).toBe('{"a":2,"b":3 }')
expect(jsonrepair('{"nested":{"a":2,"b":3, ... }}')).toBe('{"nested":{"a":2,"b":3 }}')
expect(jsonrepair('{"a":2,"b":3,...,"z":26}')).toBe('{"a":2,"b":3,"z":26}')
expect(jsonrepair('{"a":2,"b":3,...}')).toBe('{"a":2,"b":3}')
})

test('should add missing start quote', () => {
expect(jsonrepair('abc"')).toBe('"abc"')
expect(jsonrepair('[a","b"]')).toBe('["a","b"]')
Expand Down
27 changes: 27 additions & 0 deletions src/regular/jsonrepair.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,29 @@ export function jsonrepair(text: string): string {
return skipCharacter(codeBackslash)
}

/**
* Skip ellipsis like "[1,2,3,...]" or "[1,2,3,...,9]" or "[...,7,8,9]"
* or a similar construct in objects.
*/
function skipEllipsis(): boolean {
parseWhitespaceAndSkipComments()

if (
text.charCodeAt(i) === codeDot &&
text.charCodeAt(i + 1) === codeDot &&
text.charCodeAt(i + 2) === codeDot
) {
// repair: remove the ellipsis (three dots) and optionally a comma
i += 3
parseWhitespaceAndSkipComments()
skipCharacter(codeComma)

return true
}

return false
}

/**
* Parse an object like '{"key": "value"}'
*/
Expand All @@ -240,6 +263,8 @@ export function jsonrepair(text: string): string {
initial = false
}

skipEllipsis()

const processedKey = parseString() || parseUnquotedString()
if (!processedKey) {
if (
Expand Down Expand Up @@ -314,6 +339,8 @@ export function jsonrepair(text: string): string {
initial = false
}

skipEllipsis()

const processedValue = parseValue()
if (!processedValue) {
// repair trailing comma
Expand Down
26 changes: 25 additions & 1 deletion src/streaming/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ export function jsonrepairCore({
switch (stack.caret) {
case Caret.beforeKey:
return (
skipEllipsis() ||
parseObjectKey() ||
parseUnexpectedColon() ||
parseRepairTrailingComma() ||
Expand All @@ -140,7 +141,7 @@ export function jsonrepairCore({
case StackType.array: {
switch (stack.caret) {
case Caret.beforeValue:
return parseValue() || parseRepairTrailingComma() || parseRepairArrayEnd()
return skipEllipsis() || parseValue() || parseRepairTrailingComma() || parseRepairArrayEnd()
case Caret.afterValue:
return (
parseArrayComma() ||
Expand Down Expand Up @@ -524,6 +525,29 @@ export function jsonrepairCore({
return skipCharacter(codeBackslash)
}

/**
* Skip ellipsis like "[1,2,3,...]" or "[1,2,3,...,9]" or "[...,7,8,9]"
* or a similar construct in objects.
*/
function skipEllipsis(): boolean {
parseWhitespaceAndSkipComments()

if (
input.charCodeAt(i) === codeDot &&
input.charCodeAt(i + 1) === codeDot &&
input.charCodeAt(i + 2) === codeDot
) {
// repair: remove the ellipsis (three dots) and optionally a comma
i += 3
parseWhitespaceAndSkipComments()
skipCharacter(codeComma)

return true
}

return false
}

/**
* Parse a string enclosed by double quotes "...". Can contain escaped quotes
* Repair strings enclosed in single quotes or special quotes
Expand Down

0 comments on commit 019e509

Please sign in to comment.