简体   繁体   中英

Match every JSON (stringified) key and value using one regex group

I tried /("(?:[^\"]|\")*?")/g

const string = `[
 {
  "name": "total_4_dials_time",
  "type": "transform",
  "source": "long total_nodes = data.nodestats._nodes.total;\nMap res = [:];\nres[\"nodes\"] = data.nodestats._nodes.total;\nlong millis = System.currentTimeMillis();\nres[\"@time\"] = millis;\nreturn res;"
 }
]`;

const regexJSONKeysAndValues = new RegExp('("(?:[^\"]|\")*?")', 'g');
const result = string.match(regexJSONKeysAndValues);
console.log(result);

And got the "source" value splitted into three strings where is \". I don't need the "source" value splitted.

[
 '"name"',
 '"total_4_dials_time"',
 '"type"',
 '"transform"',
 '"source"',
 '"long total_nodes = data.nodestats._nodes.total;\nMap res = [:];\nres["',
 '"] = data.nodestats._nodes.total;\nlong millis = System.currentTimeMillis();\nres["',
 '"] = millis;\nreturn res;"' 
]

What regex to use to achieve the following result?

[ 
'"name"',
 '"total_4_dials_time"',
 '"type"',
 '"transform"',
 '"source"',
 '"long total_nodes = data.nodestats._nodes.total;\nMap res = [:];\nres["nodes"] = data.nodestats._nodes.total;\nlong millis = System.currentTimeMillis();\nres["@time"] = millis;return res;"'
 ]

Here is my regex playground with an example https://regex101.com/r/YTzXaV/4

I need this for my custom ace editor mode. Ace editor value is a string, not an object. The values which contain \n must be wrapped with triple-quotes. For example,

const string = `[
  {
    "name": "total_4_dials_time",
    "type": "transform",
    "source": "long total_nodes = data.nodestats._nodes.total;\nMap res = [:];\nres['nodes'] = data.nodestats._nodes.total;\nlong millis = System.currentTimeMillis();\nres['@time'] = millis;\nreturn res;"
  }
]`;

const unfoldMultiLineString = (string = '') => {
  const regexJSONKeysAndValues = new RegExp('("(?:[^\"]|\")*?")', 'g');

  return string.replace(regexJSONKeysAndValues, (match, value) => {
    const areNewLines = value.includes('\n');
    if (areNewLines) {
      return `"""\n${value.slice(1, value.length - 1)}\n"""`;
    }

    return value;
  });
};

console.log(unfoldMultiLineString(string));

Result:

[
 {
  "name": "total_4_dials_time",
  "type": "transform",
  "source": """
long total_nodes = data.nodestats._nodes.total;
Map res = [:];
res['nodes'] = data.nodestats._nodes.total;
long millis = System.currentTimeMillis();
res['@time'] = millis;
return res;
"""
 }
]

It doesn't work if "source" value contains double quotes though.

You can do this with JSON.parse if you double-escape the backslashes, so \ => \\ :

 const string = `[ { "name": "total_4_dials_time", "type": "transform", "source": "long total_nodes = data.nodestats._nodes.total;\\nMap res = [:];\\nres['nodes'] = data.nodestats._nodes.total;\\nlong millis = System.currentTimeMillis();\\nres['@time'] = millis;\\nreturn res;" } ]`; const parsed = JSON.parse(string); const result = Object.keys(parsed[0]).flatMap(k => [k, parsed[0][k]]).map(JSON.stringify); console.log(result);

Result:

[
  "\"name\"",
  "\"total_4_dials_time\"",
  "\"type\"",
  "\"transform\"",
  "\"source\"",
  "\"long total_nodes = data.nodestats._nodes.total;\\nMap res = [:];\\nres['nodes'] = data.nodestats._nodes.total;\\nlong millis = System.currentTimeMillis();\\nres['@time'] = millis;\\nreturn res;\""
]

I don't completely understand what you're looking for, let's look if this helps:

 function pythonify(obj) { let out = Object.entries(obj).map(([k, v]) => { if (typeof v === 'string' && v.includes('\n')) v = '"""\n' + v + '\n"""'; else v = JSON.stringify(v) return ' ' + JSON.stringify(k) + ': ' + v; }); return '{\n' + out.join(',\n') + '\n}' } // const string = String.raw`[ { "name": "total_4_dials_time", "type": "transform", "source": "long total_nodes = data.nodestats._nodes.total;\nMap res = [:];\nres[\"nodes\"] = data.nodestats._nodes.total;\nlong millis = System.currentTimeMillis();\nres[\"@time\"] = millis;\nreturn res;" } ]`; console.log(pythonify(JSON.parse(string)[0]))

i just went back to your https://regex101.com/r/YTzXaV/4 example and escaped the double quotes that are also escaped in your code example and used the following regex:

  • ("(?:[^\"]|\")*?[^\\]")

The only part i added being [^\\] so that the last double quote must be preceded by any character that is not a backslash

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM