feat: Add JSON Repair operation with comprehensive repair capabilities

- Add new JSON Repair operation using jsonrepair library (v3.13.0)
- Support for fixing common JSON issues:
  * Missing quotes around object keys
  * Single quotes to double quotes conversion
  * Trailing commas removal
  * Missing commas insertion
  * Python constants (True/False/None) to JSON equivalents
  * Comments removal (both // and /* */ styles)
  * JSONP notation handling
- Include comprehensive test suite with 11 test cases
- Add operation to 'Code tidy' category
- Follows KISS principle with minimal configuration
- Uses dynamic import for robust module loading

Resolves the common issue of repairing malformed JSON data,
particularly useful for processing JSON with missing commas
between object properties.

Author: maojunxyz <maojun@linux.com>
This commit is contained in:
maojunxyz 2025-08-08 17:49:43 +08:00
parent 2a1294f1c0
commit 07fbc1eda0
6 changed files with 225 additions and 0 deletions

10
package-lock.json generated
View File

@ -58,6 +58,7 @@
"json5": "^2.2.3", "json5": "^2.2.3",
"jsonata": "^2.0.3", "jsonata": "^2.0.3",
"jsonpath-plus": "^9.0.0", "jsonpath-plus": "^9.0.0",
"jsonrepair": "^3.13.0",
"jsonwebtoken": "8.5.1", "jsonwebtoken": "8.5.1",
"jsqr": "^1.4.0", "jsqr": "^1.4.0",
"jsrsasign": "^11.1.0", "jsrsasign": "^11.1.0",
@ -12520,6 +12521,15 @@
"node": ">=14.0.0" "node": ">=14.0.0"
} }
}, },
"node_modules/jsonrepair": {
"version": "3.13.0",
"resolved": "https://registry.npmjs.org/jsonrepair/-/jsonrepair-3.13.0.tgz",
"integrity": "sha512-5YRzlAQ7tuzV1nAJu3LvDlrKtBFIALHN2+a+I1MGJCt3ldRDBF/bZuvIPzae8Epot6KBXd0awRZZcuoeAsZ/mw==",
"license": "ISC",
"bin": {
"jsonrepair": "bin/cli.js"
}
},
"node_modules/jsonwebtoken": { "node_modules/jsonwebtoken": {
"version": "8.5.1", "version": "8.5.1",
"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz",

View File

@ -144,6 +144,7 @@
"json5": "^2.2.3", "json5": "^2.2.3",
"jsonata": "^2.0.3", "jsonata": "^2.0.3",
"jsonpath-plus": "^9.0.0", "jsonpath-plus": "^9.0.0",
"jsonrepair": "^3.13.0",
"jsonwebtoken": "8.5.1", "jsonwebtoken": "8.5.1",
"jsqr": "^1.4.0", "jsqr": "^1.4.0",
"jsrsasign": "^11.1.0", "jsrsasign": "^11.1.0",

View File

@ -465,6 +465,7 @@
"JavaScript Minify", "JavaScript Minify",
"JSON Beautify", "JSON Beautify",
"JSON Minify", "JSON Minify",
"JSON Repair",
"XML Beautify", "XML Beautify",
"XML Minify", "XML Minify",
"SQL Beautify", "SQL Beautify",

View File

@ -0,0 +1,48 @@
/**
* @author maojunxyz [maojun@linux.com]
* @copyright Crown Copyright 2025
* @license Apache-2.0
*/
import OperationError from "../errors/OperationError.mjs";
import Operation from "../Operation.mjs";
/**
* JSON Repair operation
*/
class JSONRepair extends Operation {
/**
* JSONRepair constructor
*/
constructor() {
super();
this.name = "JSON Repair";
this.module = "Code";
this.description = "Attempts to repair invalid JSON by fixing common issues such as missing quotes around keys, trailing commas, single quotes, missing brackets, and more.<br><br>This operation can fix:<br>• Missing quotes around keys<br>• Single quotes instead of double quotes<br>• Trailing commas<br>• Missing commas<br>• Missing closing brackets<br>• Python constants (None, True, False)<br>• Comments<br>• JSONP notation<br>• And many other common JSON formatting issues<br><br>Uses the jsonrepair library for comprehensive JSON repair.<br><br>Tags: json fix, json repair, json validate, json format";
this.inputType = "string";
this.outputType = "string";
this.args = [];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
async run(input, args) {
if (!input) return "";
try {
// Dynamic import of jsonrepair to handle potential module loading issues
const { jsonrepair } = await import("jsonrepair");
return jsonrepair(input);
} catch (err) {
throw new OperationError("Unable to repair JSON. The input contains errors that cannot be automatically fixed.\n" + err.message);
}
}
}
export default JSONRepair;

View File

@ -93,6 +93,7 @@ import "./tests/JA3SFingerprint.mjs";
import "./tests/Jsonata.mjs"; import "./tests/Jsonata.mjs";
import "./tests/JSONBeautify.mjs"; import "./tests/JSONBeautify.mjs";
import "./tests/JSONMinify.mjs"; import "./tests/JSONMinify.mjs";
import "./tests/JSONRepair.mjs";
import "./tests/JSONtoCSV.mjs"; import "./tests/JSONtoCSV.mjs";
import "./tests/Jump.mjs"; import "./tests/Jump.mjs";
import "./tests/JWK.mjs"; import "./tests/JWK.mjs";

View File

@ -0,0 +1,164 @@
/**
* JSONRepair tests.
*
* @author maojunxyz [maojun@linux.com]
*
* @copyright Crown Copyright 2025
* @license Apache-2.0
*/
import TestRegister from "../../lib/TestRegister.mjs";
TestRegister.addTests([
{
name: "JSON Repair: empty string",
input: "",
expectedOutput: "",
recipeConfig: [
{
op: "JSON Repair",
args: [],
},
],
},
{
name: "JSON Repair: valid JSON unchanged",
input: '{"name": "John", "age": 30}',
expectedOutput: '{"name": "John", "age": 30}',
recipeConfig: [
{
op: "JSON Repair",
args: [],
},
],
},
{
name: "JSON Repair: missing quotes around keys",
input: '{name: "John", age: 30}',
expectedOutput: '{"name": "John", "age": 30}',
recipeConfig: [
{
op: "JSON Repair",
args: [],
},
],
},
{
name: "JSON Repair: single quotes to double quotes",
input: "{'name': 'John', 'age': 30}",
expectedOutput: '{"name": "John", "age": 30}',
recipeConfig: [
{
op: "JSON Repair",
args: [],
},
],
},
{
name: "JSON Repair: trailing comma in object",
input: '{"name": "John", "age": 30,}',
expectedOutput: '{"name": "John", "age": 30}',
recipeConfig: [
{
op: "JSON Repair",
args: [],
},
],
},
{
name: "JSON Repair: trailing comma in array",
input: '[1, 2, 3,]',
expectedOutput: '[1, 2, 3]',
recipeConfig: [
{
op: "JSON Repair",
args: [],
},
],
},
{
name: "JSON Repair: Python constants",
input: '{"active": True, "data": None, "flag": False}',
expectedOutput: '{"active": true, "data": null, "flag": false}',
recipeConfig: [
{
op: "JSON Repair",
args: [],
},
],
},
{
name: "JSON Repair: line comments",
input: `{
"name": "John", // This is a comment
"age": 30
}`,
expectedOutput: `{
"name": "John",
"age": 30
}`,
recipeConfig: [
{
op: "JSON Repair",
args: [],
},
],
},
{
name: "JSON Repair: block comments",
input: `{
"name": "John", /* This is a
multi-line comment */
"age": 30
}`,
expectedOutput: `{
"name": "John",
"age": 30
}`,
recipeConfig: [
{
op: "JSON Repair",
args: [],
},
],
},
{
name: "JSON Repair: missing comma",
input: `{
"name": "John"
"age": 30,
"city": "Boston"
}`,
expectedOutput: `{
"name": "John",
"age": 30,
"city": "Boston"
}`,
recipeConfig: [
{
op: "JSON Repair",
args: [],
},
],
},
{
name: "JSON Repair: complex mixed issues",
input: `{
name: 'John', // Person's name
age: 30,
active: True,
data: None,
}`,
expectedOutput: `{
"name": "John",
"age": 30,
"active": true,
"data": null
}`,
recipeConfig: [
{
op: "JSON Repair",
args: [],
},
],
},
]);