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>")