Skip to content

Commit

Permalink
Escape reserved characters in JSON strings
Browse files Browse the repository at this point in the history
  • Loading branch information
kpeters-cbsi committed Dec 2, 2020
1 parent 869b411 commit 892a01c
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 1 deletion.
15 changes: 14 additions & 1 deletion assembly/JSON.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,20 @@ export namespace JSON {
}

toString(): string {
return "\"" + this._str + "\"";
let escaped: i32[] = [];
for (let i = 0; i < this._str.length; i++) {
const charCode = this._str.charCodeAt(i)
const char = this._str.charAt(i)
if (
charCode == 0x22 || // " quotation mark U+0022
charCode == 0x5C || // \ reverse solidus U+005C
charCode < 0x20 // control characters
) {
escaped.push(0x5c); // add a reverse solidus (backslash) to escape reserved chars
}
escaped.push(charCode)
}
return "\"" + String.fromCharCodes(escaped) + "\"";
}
}

Expand Down
53 changes: 53 additions & 0 deletions assembly/__tests__/string_escape.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { JSON } from '../JSON'

describe('Escaped characters', () => {
it('Does not escape characters unneccessarily', () => {
const strings = [
'sphinx of black quartz, judge my vow',
'{}',
'[]',
'/',
'|',
'/|||/|||[{]}<>,.',
'ஂ ஃ அ ஆ இ ஈ உ ஊ எ ஏ ஐ ஒ ஓ ஔ க ங ச ஜ ஞ ட ண த ந ன ப ம ய ர ற ல ள',
'ᄀ ᄁ ᄂ ᄃ ᄄ ᄅ ᄆ ᄇ ᄈ ᄉ ᄊ ᄋ ᄌ ᄍ ᄎ ᄏ ᄐ ᄑ ᄒ ᄓ ᄔ ᄕ ᄖ ᄗ ᄘ ᄙ ᄚ ᄛ ',
'℀ ℁ ℂ ℃ ℄ ℅ ℆ ℇ ℈ ℉ ℊ ℋ ℌ ℍ ℎ ℏ ℐ ℑ ℒ ℓ ℔ ℕ № ℗ ℘ ℙ ℚ ℛ ℜ ℝ ℞ ℟ ℠ ℡ ™ ℣ ℤ ℥ Ω ℧ ℨ ℩ K Å ℬ ℭ ℮ ℯ ℰ ℱ Ⅎ ℳ ℴ ℵ ℶ ℷ ℸ ',
'☀ ☁ ☂ ☃ ☄ ★ ☆ ☇ ☈ ☉ ☊ ☋ ☌ ☍ ☎ ☏ ☐ ☑ ☒ ☓ ☚ ☛ ☜ ☝ ☞ ☟ ☠ ☡ ☢ ☣ ☤ ☥ ☦ ☧ ☨ ☩ ☪ ☫ ☬ ☭ ☮ ☯ ☰ ☱ ☲ ☳ ☴ ☵ ☶ ☷ ☸ ☹ ☺ ☻ ☼ ☽ ☾ ☿ ♀ ♁ ♂ ♃ ♄ ♅ ♆ ♇ ♈ ♉ ♊ ♋ ♌ ♍ ♎ ♏ ♐ ♑ ♒ ♓',
]
strings.forEach((str) => {
const jsonStr = new JSON.Str(str)
expect(jsonStr.toString()).toBe('"' + str + '"')
})
})
it('Escapes quotes and backslashes', () => {
const strings = ['"', '\\', '"\\"', '\\"\\"']
strings.forEach((str) => {
const jsonStr = new JSON.Str(str)
expect(jsonStr.toString()).toBe('"' + escaped(str) + '"')
})
})
it('Escapes control characters', () => {
const strings = ['\n', '\r', '\r\n', '\b', '\f', '\t', '\v', '\b\f\t\v\r']
strings.forEach((str) => {
const jsonStr = new JSON.Str(str)
expect(jsonStr.toString()).toBe('"' + escaped(str) + '"')
})
})
})

function escaped(str: string): string {
const escapedChars: i32[] = []
for (let i = 0; i < str.length; i++) {
const charCode = str.charCodeAt(i)
if (
charCode < 0x20 || // control characters
charCode == 0x22 || // double quote (")
charCode == 0x5c
) {
// backslash / reverse solidus (\)
escapedChars.push(0x5c)
}
escapedChars.push(charCode)
}
return String.fromCharCodes(escapedChars)
}

0 comments on commit 892a01c

Please sign in to comment.