From 0b4b2df49382609ad7bb43c61157091ce6061990 Mon Sep 17 00:00:00 2001 From: Anoop M D Date: Sun, 26 Oct 2025 14:45:10 +0530 Subject: [PATCH 1/6] feat: add lossless-json to benchmark and update performance metrics --- benchmark.js | 16 ++++++++++++---- package-lock.json | 14 +++++++++++--- package.json | 3 ++- readme.md | 12 ++++++------ 4 files changed, 31 insertions(+), 14 deletions(-) diff --git a/benchmark.js b/benchmark.js index 77b312d..ec8a593 100644 --- a/benchmark.js +++ b/benchmark.js @@ -3,6 +3,7 @@ const { faker } = require('@faker-js/faker'); const chalk = require('chalk'); const fastJsonFormat = require('./src/index.js'); const JSONbig = require('json-bigint'); +const LosslessJSON = require('lossless-json'); /** * Generates a nested JSON string of approximately the target size @@ -75,7 +76,7 @@ const testSizes = [ ]; console.log('\n' + chalk.bold.cyan('πŸš€ Fast JSON Format Benchmark') + '\n'); -console.log(chalk.gray('⚑ Comparing ') + chalk.yellow('fast-json-format') + chalk.gray(' vs ') + chalk.yellow('JSON.stringify(JSON.parse())') + chalk.gray(' vs ') + chalk.yellow('json-bigint') + '\n'); +console.log(chalk.gray('⚑ Comparing ') + chalk.yellow('fast-json-format') + chalk.gray(' vs ') + chalk.yellow('JSON.stringify(JSON.parse())') + chalk.gray(' vs ') + chalk.yellow('json-bigint') + chalk.gray(' vs ') + chalk.yellow('lossless-json') + '\n'); console.log(chalk.bold.blue('πŸ“Š Generating test data...') + '\n'); const testCases = testSizes.map(size => { @@ -110,6 +111,9 @@ testCases.forEach(testCase => { .add('json-bigint', function() { JSONbig.stringify(JSONbig.parse(testCase.data), null, 2); }) + .add('lossless-json', function() { + LosslessJSON.stringify(LosslessJSON.parse(testCase.data), null, 2); + }) .add('JSON.stringify', function() { JSON.stringify(JSON.parse(testCase.data), null, 2); }) @@ -121,7 +125,7 @@ testCases.forEach(testCase => { results.push({ name, hz: event.target.hz }); const symbol = results.length === 1 ? 'β”œβ”€' : results.length === 2 ? 'β”œβ”€' : '└─'; - const color = name === 'fast-json-format' ? chalk.green : name === 'JSON.stringify' ? chalk.blue : chalk.magenta; + const color = name === 'fast-json-format' ? chalk.green : name === 'JSON.stringify' ? chalk.blue : name === 'json-bigint' ? chalk.magenta : chalk.yellow; console.log(chalk.gray(` ${symbol} `) + color(name) + chalk.gray(': ') + chalk.bold.white(ops) + chalk.gray(' ops/sec Β±' + margin + '%')); }) @@ -143,7 +147,7 @@ testCases.forEach(testCase => { console.log('\n\n' + chalk.bold.cyan('πŸ“Š Summary Table') + '\n'); // Build table header -const libs = ['fast-json-format', 'json-bigint', 'JSON.stringify']; +const libs = ['fast-json-format', 'json-bigint', 'lossless-json', 'JSON.stringify']; const colWidths = { size: 12, lib: 20 }; // Header @@ -151,24 +155,28 @@ console.log( chalk.bold.white('Size'.padEnd(colWidths.size)) + ' β”‚ ' + chalk.bold.green('fast-json-format'.padEnd(colWidths.lib)) + ' β”‚ ' + chalk.bold.magenta('json-bigint'.padEnd(colWidths.lib)) + ' β”‚ ' + + chalk.bold.yellow('lossless-json'.padEnd(colWidths.lib)) + ' β”‚ ' + chalk.bold.blue('JSON.stringify'.padEnd(colWidths.lib)) ); -console.log('─'.repeat(colWidths.size) + '─┼─' + '─'.repeat(colWidths.lib) + '─┼─' + '─'.repeat(colWidths.lib) + '─┼─' + '─'.repeat(colWidths.lib)); +console.log('─'.repeat(colWidths.size) + '─┼─' + '─'.repeat(colWidths.lib) + '─┼─' + '─'.repeat(colWidths.lib) + '─┼─' + '─'.repeat(colWidths.lib) + '─┼─' + '─'.repeat(colWidths.lib)); // Rows allResults.forEach(result => { const fastJson = result.results.find(r => r.name === 'fast-json-format'); const jsonBigint = result.results.find(r => r.name === 'json-bigint'); + const losslessJson = result.results.find(r => r.name === 'lossless-json'); const jsonStringify = result.results.find(r => r.name === 'JSON.stringify'); const fastJsonOps = fastJson ? fastJson.hz.toFixed(0) : 'N/A'; const jsonBigintOps = jsonBigint ? jsonBigint.hz.toFixed(0) : 'N/A'; + const losslessJsonOps = losslessJson ? losslessJson.hz.toFixed(0) : 'N/A'; const jsonStringifyOps = jsonStringify ? jsonStringify.hz.toFixed(0) : 'N/A'; console.log( chalk.cyan(result.size.padEnd(colWidths.size)) + ' β”‚ ' + chalk.white((fastJsonOps + ' ops/sec').padEnd(colWidths.lib)) + ' β”‚ ' + chalk.white((jsonBigintOps + ' ops/sec').padEnd(colWidths.lib)) + ' β”‚ ' + + chalk.white((losslessJsonOps + ' ops/sec').padEnd(colWidths.lib)) + ' β”‚ ' + chalk.white((jsonStringifyOps + ' ops/sec').padEnd(colWidths.lib)) ); }); diff --git a/package-lock.json b/package-lock.json index 55a14bd..efaacaa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,19 +1,20 @@ { "name": "fast-json-format", - "version": "0.0.1", + "version": "0.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "fast-json-format", - "version": "0.0.1", + "version": "0.1.0", "license": "MIT", "devDependencies": { "@faker-js/faker": "^9.9.0", "benchmark": "^2.1.4", "chalk": "^4.1.2", "jest": "^30.2.0", - "json-bigint": "^1.0.0" + "json-bigint": "^1.0.0", + "lossless-json": "^4.3.0" } }, "node_modules/@babel/code-frame": { @@ -3257,6 +3258,13 @@ "dev": true, "license": "MIT" }, + "node_modules/lossless-json": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lossless-json/-/lossless-json-4.3.0.tgz", + "integrity": "sha512-ToxOC+SsduRmdSuoLZLYAr5zy1Qu7l5XhmPWM3zefCZ5IcrzW/h108qbJUKfOlDlhvhjUK84+8PSVX0kxnit0g==", + "dev": true, + "license": "MIT" + }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", diff --git a/package.json b/package.json index 6e3e40d..bb3426c 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,8 @@ "benchmark": "^2.1.4", "chalk": "^4.1.2", "jest": "^30.2.0", - "json-bigint": "^1.0.0" + "json-bigint": "^1.0.0", + "lossless-json": "^4.3.0" }, "license": "MIT" } diff --git a/readme.md b/readme.md index f593ec6..8ba8482 100644 --- a/readme.md +++ b/readme.md @@ -64,12 +64,12 @@ JSON.stringify is inherently faster (as it’s native and C++-optimized) Performance improvements are welcome :) ```text -Size β”‚ fast-json-format β”‚ json-bigint β”‚ JSON.stringify -─────────────┼──────────────────────┼──────────────────────┼───────────────────── -100 KB β”‚ 1060 ops/sec β”‚ 679 ops/sec β”‚ 2394 ops/sec -1 MB β”‚ 90 ops/sec β”‚ 68 ops/sec β”‚ 223 ops/sec -5 MB β”‚ 15 ops/sec β”‚ 13 ops/sec β”‚ 48 ops/sec -10 MB β”‚ 7 ops/sec β”‚ 6 ops/sec β”‚ 23 ops/sec +Size β”‚ fast-json-format β”‚ json-bigint β”‚ lossless-json β”‚ JSON.stringify +─────────────┼──────────────────────┼──────────────────────┼──────────────────────┼───────────────────── +100 KB β”‚ 1064 ops/sec β”‚ 712 ops/sec β”‚ 609 ops/sec β”‚ 2432 ops/sec +1 MB β”‚ 91 ops/sec β”‚ 65 ops/sec β”‚ 43 ops/sec β”‚ 238 ops/sec +5 MB β”‚ 15 ops/sec β”‚ 13 ops/sec β”‚ 6 ops/sec β”‚ 47 ops/sec +10 MB β”‚ 7 ops/sec β”‚ 7 ops/sec β”‚ 3 ops/sec β”‚ 23 ops/sec ``` ## Testing From 62a33448ab4795b3dbad64f62566397500260ded Mon Sep 17 00:00:00 2001 From: Anoop M D Date: Sun, 26 Oct 2025 14:47:30 +0530 Subject: [PATCH 2/6] release: bump version to 0.2.0 and add prepack script --- package-lock.json | 4 ++-- package.json | 8 +++++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index efaacaa..fec7b04 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "fast-json-format", - "version": "0.1.0", + "version": "0.2.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "fast-json-format", - "version": "0.1.0", + "version": "0.2.0", "license": "MIT", "devDependencies": { "@faker-js/faker": "^9.9.0", diff --git a/package.json b/package.json index bb3426c..799cce6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "fast-json-format", - "version": "0.1.0", + "version": "0.2.0", "description": "Fast JSON formatting library", "main": "src/index.js", "keywords": [ @@ -9,8 +9,14 @@ "fast", "json-format" ], + "files": [ + "src", + "package.json", + "readme.md" + ], "author": "Bruno Software Inc.", "scripts": { + "prepack": "npm run test", "benchmark": "node benchmark.js", "test": "jest tests/*.spec.js" }, From d2e8d9c10ff968792e02d9af2ba53aebb0438a05 Mon Sep 17 00:00:00 2001 From: Anoop M D Date: Sun, 9 Nov 2025 18:51:47 +0530 Subject: [PATCH 3/6] feat: enhance unicode handling by decoding \uXXXX sequences to match parity with JSON.stringify --- src/index.js | 77 +++++++++++++++++++++++++----- tests/unicode.spec.js | 106 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 171 insertions(+), 12 deletions(-) create mode 100644 tests/unicode.spec.js diff --git a/src/index.js b/src/index.js index 1def0cd..fb72f44 100644 --- a/src/index.js +++ b/src/index.js @@ -65,33 +65,86 @@ function fastJsonFormat(input, indent = ' ') { return idx; }; + // Helper: check if character code is a valid hex digit (0-9, A-F, a-f) + const isHexDigit = (code) => { + return (code >= 48 && code <= 57) || // 0-9 + (code >= 65 && code <= 70) || // A-F + (code >= 97 && code <= 102); // a-f + }; + + // Helper: parse 4 hex digits starting at position j + // Returns -1 if invalid, otherwise the code point + const parseHex4 = (j) => { + if (j + 4 > n) return -1; + const c1 = s.charCodeAt(j); + const c2 = s.charCodeAt(j + 1); + const c3 = s.charCodeAt(j + 2); + const c4 = s.charCodeAt(j + 3); + if (!isHexDigit(c1) || !isHexDigit(c2) || !isHexDigit(c3) || !isHexDigit(c4)) { + return -1; + } + // Fast hex parsing without parseInt + let val = 0; + // First digit + val = c1 <= 57 ? c1 - 48 : (c1 <= 70 ? c1 - 55 : c1 - 87); + // Second digit + val = (val << 4) | (c2 <= 57 ? c2 - 48 : (c2 <= 70 ? c2 - 55 : c2 - 87)); + // Third digit + val = (val << 4) | (c3 <= 57 ? c3 - 48 : (c3 <= 70 ? c3 - 55 : c3 - 87)); + // Fourth digit + val = (val << 4) | (c4 <= 57 ? c4 - 48 : (c4 <= 70 ? c4 - 55 : c4 - 87)); + return val; + }; + // Scan a JSON string starting at index of opening quote `i` (s[i] === '"'). - // Returns index just after the closing quote and pushes the entire slice. + // Returns index just after the closing quote and decodes \uXXXX sequences. const scanString = (i) => { + out.push('"'); // opening quote let j = i + 1; + let lastCopy = j; // track where we last copied from + while (j < n) { const c = s.charCodeAt(j); if (c === QUOTE) { // end of string - j++; - out.push(s.slice(i, j)); - return j; + // Copy any remaining content before the closing quote + if (j > lastCopy) { + out.push(s.slice(lastCopy, j)); + } + out.push('"'); // closing quote + return j + 1; } if (c === BACKSLASH) { - // Handle escape: \" \\ \/ \b \f \n \r \t or \uXXXX + const backslashPos = j; j++; if (j < n && s.charCodeAt(j) === 117 /* 'u' */) { - // Skip 'u' + 4 hex digits if present - // (Keep it forgiving; don't validate hex strictly) - j += 5; // 'u' + 4 chars - } else { - j++; // skip the escaped char + // Found \uXXXX - try to decode it to actual unicode character + const codePoint = parseHex4(j + 1); + + if (codePoint >= 0) { + // Valid hex sequence - decode it + // Copy everything up to the backslash + if (backslashPos > lastCopy) { + out.push(s.slice(lastCopy, backslashPos)); + } + // Convert to actual unicode character + out.push(String.fromCharCode(codePoint)); + j += 5; // skip 'u' + 4 hex digits + lastCopy = j; + continue; + } + // If parsing failed, reset and let it be copied as-is + j = backslashPos + 1; } + // For other escapes (or invalid \u), just skip the escaped char + if (j < n) j++; continue; } j++; } - // Unterminated: copy to end (forgiving) - out.push(s.slice(i, n)); + // Unterminated: copy remaining content (forgiving) + if (n > lastCopy) { + out.push(s.slice(lastCopy, n)); + } return n; }; diff --git a/tests/unicode.spec.js b/tests/unicode.spec.js new file mode 100644 index 0000000..74e8396 --- /dev/null +++ b/tests/unicode.spec.js @@ -0,0 +1,106 @@ +const { assertEqual } = require('./utils'); +const fastJsonFormat = require('../src/index'); + +describe('unicode handling', () => { + it('should decode \\uXXXX escape sequences to unicode characters', () => { + const input = '{"name":"\\u4e16\\u754c"}'; + const expected = `{ + "name": "δΈ–η•Œ" +}`; + assertEqual(input, expected); + }); + + it('should handle mixed ASCII and unicode escapes', () => { + const input = '{"greeting":"Hello \\u4e16\\u754c"}'; + const expected = `{ + "greeting": "Hello δΈ–η•Œ" +}`; + assertEqual(input, expected); + }); + + it('should decode multiple unicode strings', () => { + const input = '{"chinese":"\\u4f60\\u597d","japanese":"\\u3053\\u3093\\u306b\\u3061\\u306f"}'; + const expected = `{ + "chinese": "δ½ ε₯½", + "japanese": "こんにけは" +}`; + assertEqual(input, expected); + }); + + it('should handle emoji surrogate pairs', () => { + const input = '{"emoji":"\\ud83d\\ude00"}'; + const expected = `{ + "emoji": "πŸ˜€" +}`; + assertEqual(input, expected); + }); + + it('should decode unicode in nested objects', () => { + const input = '{"outer":{"inner":"\\u4e2d\\u6587"}}'; + const expected = `{ + "outer": { + "inner": "δΈ­ζ–‡" + } +}`; + assertEqual(input, expected); + }); + + it('should handle unicode in array values', () => { + const input = '["\\u4e00","\\u4e8c","\\u4e09"]'; + const expected = `[ + "δΈ€", + "二", + "δΈ‰" +]`; + assertEqual(input, expected); + }); + + it('should handle uppercase hex in unicode escapes', () => { + const input = '{"text":"\\u4E16\\u754C"}'; + const expected = `{ + "text": "δΈ–η•Œ" +}`; + assertEqual(input, expected); + }); + + it('should preserve invalid unicode escapes as-is', () => { + // Note: This is invalid JSON that JSON.parse would reject + // Testing forgiving behavior only + const input = '{"invalid":"\\uXYZ"}'; + const expected = `{ + "invalid": "\\uXYZ" +}`; + expect(fastJsonFormat(input)).toBe(expected); + }); + + it('should preserve incomplete unicode escapes as-is', () => { + // Note: This is invalid JSON that JSON.parse would reject + // Testing forgiving behavior only + const input = '{"incomplete":"\\u12"}'; + const expected = `{ + "incomplete": "\\u12" +}`; + expect(fastJsonFormat(input)).toBe(expected); + }); + + it('should handle unicode mixed with other escape sequences', () => { + const input = '{"text":"\\u4e16\\n\\u754c\\t\\u0021"}'; + const expected = `{ + "text": "δΈ–\\nη•Œ\\t!" +}`; + assertEqual(input, expected); + }); + + it('should behave like JSON.stringify for unicode content', () => { + // JSON.stringify preserves actual unicode characters (doesn't escape them) + const obj = { name: "δΈ–η•Œ" }; + const fromStringify = JSON.stringify(obj, null, 2); + + // fastJsonFormat should decode \uXXXX to match that behavior + const input = '{"name":"\\u4e16\\u754c"}'; + const fromFormatter = fastJsonFormat(input); + + expect(fromFormatter).toBe(fromStringify); + }); +}); + From 72775714fdda945180e597804bc53226d5c37554 Mon Sep 17 00:00:00 2001 From: Anoop M D Date: Sun, 9 Nov 2025 18:52:15 +0530 Subject: [PATCH 4/6] release: bump version to 0.3.0 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index fec7b04..ae3f30d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "fast-json-format", - "version": "0.2.0", + "version": "0.3.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "fast-json-format", - "version": "0.2.0", + "version": "0.3.0", "license": "MIT", "devDependencies": { "@faker-js/faker": "^9.9.0", diff --git a/package.json b/package.json index 799cce6..69cea74 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "fast-json-format", - "version": "0.2.0", + "version": "0.3.0", "description": "Fast JSON formatting library", "main": "src/index.js", "keywords": [ From 5497dcdf1a1a9883e08de595ff503ba2821e148a Mon Sep 17 00:00:00 2001 From: sreelakshmi-bruno Date: Wed, 12 Nov 2025 11:30:27 +0530 Subject: [PATCH 5/6] decode forward slash --- src/index.js | 14 +++++++++++- tests/escaped.spec.js | 51 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/src/index.js b/src/index.js index fb72f44..d64ac96 100644 --- a/src/index.js +++ b/src/index.js @@ -1,6 +1,7 @@ /** * Pretty-prints a JSON-like string without parsing. * Fast path: chunked copying, fast string scan, lookahead for empty {} / []. + * Decodes \uXXXX unicode sequences and \/ forward slash escapes for readability. * * @param {string} input * @param {string} indent @@ -45,6 +46,7 @@ function fastJsonFormat(input, indent = ' ') { // Character codes const QUOTE = 34; // " const BACKSLASH = 92; // \ + const FORWARD_SLASH = 47;// / const OPEN_BRACE = 123; // { const CLOSE_BRACE = 125; // } const OPEN_BRACKET = 91; // [ @@ -97,7 +99,7 @@ function fastJsonFormat(input, indent = ' ') { }; // Scan a JSON string starting at index of opening quote `i` (s[i] === '"'). - // Returns index just after the closing quote and decodes \uXXXX sequences. + // Returns index just after the closing quote and decodes \uXXXX and \/ sequences. const scanString = (i) => { out.push('"'); // opening quote let j = i + 1; @@ -134,6 +136,16 @@ function fastJsonFormat(input, indent = ' ') { } // If parsing failed, reset and let it be copied as-is j = backslashPos + 1; + } else if (j < n && s.charCodeAt(j) === FORWARD_SLASH) { + // Found \/ - decode to / for readability + // Copy everything up to the backslash + if (backslashPos > lastCopy) { + out.push(s.slice(lastCopy, backslashPos)); + } + out.push('/'); + j++; // skip the forward slash + lastCopy = j; + continue; } // For other escapes (or invalid \u), just skip the escaped char if (j < n) j++; diff --git a/tests/escaped.spec.js b/tests/escaped.spec.js index 6aa70c8..a97b77c 100644 --- a/tests/escaped.spec.js +++ b/tests/escaped.spec.js @@ -66,4 +66,55 @@ describe('escaped characters', () => { }`; assertEqual(input, expected); }); +}); + +describe('forward slash escape sequences', () => { + it('should decode \\/ escape sequences to forward slashes', () => { + const input = '{"url":"https:\\/\\/example.com\\/api\\/v1"}'; + const expected = `{ + "url": "https://example.com/api/v1" +}`; + assertEqual(input, expected); + }); + + it('should handle unescaped forward slashes correctly', () => { + const input = '{"url":"https://example.com/api/v1"}'; + const expected = `{ + "url": "https://example.com/api/v1" +}`; + assertEqual(input, expected); + }); + + it('should handle forward slashes mixed with other escape sequences', () => { + const input = '{"text":"line1\\npath\\/to\\/file\\ttab","unicode":"\\u4e16\\u754c\\/path"}'; + const expected = `{ + "text": "line1\\npath/to/file\\ttab", + "unicode": "δΈ–η•Œ/path" +}`; + assertEqual(input, expected); + }); + + it('should handle a single escaped forward slash', () => { + const input = '{"slash":"\\/"}'; + const expected = `{ + "slash": "/" +}`; + assertEqual(input, expected); + }); + + it('should handle multiple consecutive escaped forward slashes', () => { + const input = '{"path":"\\/\\/network\\/share"}'; + const expected = `{ + "path": "//network/share" +}`; + assertEqual(input, expected); + }); + + it('should handle escaped forward slash at end of string', () => { + const input = '{"url":"https://example.com\\/"}'; + const expected = `{ + "url": "https://example.com/" +}`; + assertEqual(input, expected); + }); }); \ No newline at end of file From a28022fd6fcdce8cd5bf22b655b98d2a4c3c9931 Mon Sep 17 00:00:00 2001 From: Anoop M D Date: Wed, 12 Nov 2025 14:22:35 +0530 Subject: [PATCH 6/6] release: bump version to 0.4.0 and add GitHub Actions workflow for testing --- .github/workflows/test.yml | 26 ++++++++++++++++++++++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 29 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/test.yml diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..24abf5a --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,26 @@ +name: Tests +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + test: + name: Tests + timeout-minutes: 60 + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - uses: actions/checkout@v5 + - uses: actions/setup-node@v5 + with: + node-version-file: '.nvmrc' + cache: 'npm' + cache-dependency-path: './package-lock.json' + - name: Install dependencies + run: npm i + + - name: Test + run: npm run test \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index ae3f30d..d67be34 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "fast-json-format", - "version": "0.3.0", + "version": "0.4.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "fast-json-format", - "version": "0.3.0", + "version": "0.4.0", "license": "MIT", "devDependencies": { "@faker-js/faker": "^9.9.0", diff --git a/package.json b/package.json index 69cea74..dd4da43 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "fast-json-format", - "version": "0.3.0", + "version": "0.4.0", "description": "Fast JSON formatting library", "main": "src/index.js", "keywords": [