UNPKG

fast-json-stringify

Version:
147 lines (133 loc) 3.89 kB
'use strict' // eslint-disable-next-line const STR_ESCAPE = /[\u0000-\u001f\u0022\u005c\ud800-\udfff]|[\ud800-\udbff](?![\udc00-\udfff])|(?:[^\ud800-\udbff]|^)[\udc00-\udfff]/ module.exports = class Serializer { constructor (options = {}) { switch (options.rounding) { case 'floor': this.parseInteger = Math.floor break case 'ceil': this.parseInteger = Math.ceil break case 'round': this.parseInteger = Math.round break default: this.parseInteger = Math.trunc break } } asInteger (i) { if (typeof i === 'bigint') { return i.toString() } else if (Number.isInteger(i)) { return '' + i } else { /* eslint no-undef: "off" */ const integer = this.parseInteger(i) if (Number.isNaN(integer) || !Number.isFinite(integer)) { throw new Error(`The value "${i}" cannot be converted to an integer.`) } else { return '' + integer } } } asNumber (i) { const num = Number(i) if (Number.isNaN(num)) { throw new Error(`The value "${i}" cannot be converted to a number.`) } else if (!Number.isFinite(num)) { return null } else { return '' + num } } asBoolean (bool) { return bool && 'true' || 'false' // eslint-disable-line } asDateTime (date) { if (date === null) return '""' if (date instanceof Date) { return '"' + date.toISOString() + '"' } if (typeof date === 'string') { return '"' + date + '"' } throw new Error(`The value "${date}" cannot be converted to a date-time.`) } asDate (date) { if (date === null) return '""' if (date instanceof Date) { return '"' + new Date(date.getTime() - (date.getTimezoneOffset() * 60000)).toISOString().slice(0, 10) + '"' } if (typeof date === 'string') { return '"' + date + '"' } throw new Error(`The value "${date}" cannot be converted to a date.`) } asTime (date) { if (date === null) return '""' if (date instanceof Date) { return '"' + new Date(date.getTime() - (date.getTimezoneOffset() * 60000)).toISOString().slice(11, 19) + '"' } if (typeof date === 'string') { return '"' + date + '"' } throw new Error(`The value "${date}" cannot be converted to a time.`) } asString (str) { const quotes = '"' if (str instanceof Date) { return quotes + str.toISOString() + quotes } else if (str === null) { return quotes + quotes } else if (str instanceof RegExp) { str = str.source } else if (typeof str !== 'string') { str = str.toString() } // Fast escape chars check if (!STR_ESCAPE.test(str)) { return quotes + str + quotes } if (str.length < 42) { return this.asStringSmall(str) } else { return JSON.stringify(str) } } // magically escape strings for json // relying on their charCodeAt // everything below 32 needs JSON.stringify() // every string that contain surrogate needs JSON.stringify() // 34 and 92 happens all the time, so we // have a fast case for them asStringSmall (str) { const l = str.length let result = '' let last = 0 let found = false let surrogateFound = false let point = 255 // eslint-disable-next-line for (var i = 0; i < l && point >= 32; i++) { point = str.charCodeAt(i) if (point >= 0xD800 && point <= 0xDFFF) { // The current character is a surrogate. surrogateFound = true } if (point === 34 || point === 92) { result += str.slice(last, i) + '\\' last = i found = true } } if (!found) { result = str } else { result += str.slice(last) } return ((point < 32) || (surrogateFound === true)) ? JSON.stringify(str) : '"' + result + '"' } }