Home > Enterprise >  How to fix invalid JSON with RegExp in Javascript?
How to fix invalid JSON with RegExp in Javascript?

Time:12-19

This is what I've tried

// input
let input = "{id: 1, name: apple, qty: 2, colors: [{id: 1, hex: #f95}], store: {id: 1, name: Apple Store}}"

let result = input.replace((/([\w] )(:)/g), "\"$1\"$2");
// {"id": 1, "name": apple, "qty": 2, "colors": [{"id": 1, "hex": #f95}], "store": {"id": 1, "name": Apple Store}}

And then I just replace it like, replaceAll(': ', ': "'). I think it's not good practice to resolve it, may there is someone who can help me with this problem, thank you so much.

CodePudding user response:

You can convert the stated string that looks almost like an object into an actual JavaScript object with the following assumptions:

  • keys are composed of alphanumeric and underscores chars
  • values are treated as numbers if they have the format of a number, e.g. an optional minus sign, followed by digits with optional .
  • values are treated as a string unless it has the form of a number, or start with [ (array) or { (object)
  • string values may not contain , or }

const input = "{id: 1, name: apple, qty: 2, colors: [{id: 1, hex: #f95}], store: {id: 1, name: Apple Store}}";
const regex1 = /([,\{] *)(\w ):/g;
const regex2 = /([,\{] *"\w ":)(?! *-?[0-9\.] [,\}])(?! *[\{\[])( *)([^,\}]*)/g;
let json = input
  .replace(regex1, '$1"$2":')
  .replace(regex2, '$1$2"$3"')
let result = JSON.parse(json);
console.log(JSON.stringify(result, null, ' '));

Output:

{
 "id": 1,
 "name": "apple",
 "qty": 2,
 "colors": [
  {
   "id": 1,
   "hex": "#f95"
  }
 ],
 "store": {
  "id": 1,
  "name": "Apple Store"
 }
}

Explanation of regex1:

  • ([,\{] *) -- capture group 1: , or {, followed by optional spaces
  • (\w ) -- capture group 2: 1 word chars (alphanumeric and underscore)
  • : -- literal :
  • replace '$1"$2":' -- capture group 1, followed by capture group 2 enclosed in quotes, followed by colon

Explanation of regex2:

  • ([,\{] *"\w ":) -- capture group 1: , or {, followed by optional spaces, quote, 1 word chars, quote, colon
  • (?! *-?[0-9\.] [,\}]) -- negative lookahead for optional spaces, a number, followed by , or }
  • (?! *[\{\[]) -- negative lookahead for optional spaces, followed by { or [
  • ( *) -- capture group 2: optional spaces
  • ([^,\}]*) -- capture group 3: everything that is not a , or }
  • replace '$1$2"$3"' -- capture group 1, followed by capture group 2, followed by capture group 3 enclosed in quotes

Learn more about regex: https://twiki.org/cgi-bin/view/Codev/TWikiPresentation2018x10x14Regex

CodePudding user response:

Thanks for all answers, I tried this way and its works

    class FixJson {
        constructor() {
            this.run = (json) => {
                const fixDataType = (json) => {
                    for (const key in json) {
                        if (json.hasOwnProperty(key)) {
                            const value = json[key];
                            if (typeof value === 'object') {
                                fixDataType(value);
                            } else if (value === 'true' || value === 'false') {
                                json[key] = value === 'true';
                            } else if (!isNaN(value)) {
                                json[key] = Number(value);
                            }
                        }
                    }
                    return json;
                }
    
                // use the replace function to add double quotes around the property names
                const fixedJson = json.replace(/([a-zA-Z0-9!@#\$%\^\&*\)\( =._-] )/g, '"$1"');
    
                // use the JSON.parse function to parse the fixed JSON string into a JavaScript object
                const obj = JSON.parse(fixedJson);
    
                // fix json data type, and return the result
                return fixDataType(obj)
            }
        }
    }

    const fix = new FixJson()
    let result = fix.run("<your_invalid_json>")
  • Related