I need a solution to only exchange pairs of single quotes, which are NOT within a pair of double quotes.
A simplified example (original is > 100 KB):
['Element1',"Element's2",{"Element3":"E3"},'Element4']
In this example Element's2 should not become Element"s2, but 'Element1' should become "Element1".
Background: I need to extract some website data contained in big Javascript blocks. To get it i need JOSN.parse() which does not accept single quotes (') as quotes.
but i can not simply use replace(/'/g, '"')
, because the single quote is also used as apostrophe in some texts like: "that's it".
BTW: As @hakre recommenced, a much more simple solution for my case was to use eval()
instead of JOSN.parse()
. With eval()
there was no need to exchange the single quotes.
I made a second variant, which also cares about escaped quotes like:[\'Element1\',"Element's2",{"Elements3":"E3"},'Element\'s4']
but it is a bit slower and the code looks a bit more complicated (so i use the other variant):
function convert(input) {
var openQuote
var close = {symbol:null,level:0,firstPos:null}
openQuote = close;
const singleQuote = "'"
const doubleQuote = '"'
const replaceBy = '"'
var pairCount = 0
var data = Array.from(input)
function replacePair(data, newChar, firstPos, secondPos) {
data[firstPos] = newChar;
data[secondPos] = newChar;
pairCount++
}
function checkEscaped (data, pos, level = 0) {
if (pos <= 0) return level
if (data[pos-1] == "\\") { return checkEscaped(data,pos-1,level+1) }
return level
}
function checkQuotes(data,pos){
if (data[pos] == singleQuote) {
let level = checkEscaped(data, pos)
if (openQuote.symbol == null) {openQuote = {symbol: singleQuote, level: level, firstPos: pos}; return}
if (openQuote.symbol == singleQuote && openQuote.level == level) {replacePair(data,replaceBy,openQuote.firstPos,pos); openQuote = close; return;}
return
}
if (data[pos] == doubleQuote) {
let level = checkEscaped(data, pos)
if (openQuote.symbol == null) {openQuote = {symbol: doubleQuote, level: level, firstPos: pos}; return}
if (openQuote.symbol == doubleQuote && openQuote.level == level) {openQuote = close; return;}
}
}
for (let i=0; i < data.length; i++) {
checkQuotes(data,i)
}
var result = data.join("");
console.log(pairCount , "Pairs of Single Quotes exchanged")
return result
}
document.getElementById('start').addEventListener('click', () => {
var dataIn = document.getElementById('input').value;
var output = document.getElementById('output').value = convert(dataIn)
});
<html><body>
<button id="start">start</button><BR>
Input:<br><textarea id="input" name="w3review" rows="2" cols="100" spellcheck="false">
[\'Element1\',"Element's2",{"Elements3":"E3"},'Element\'s4']
</textarea><BR>
Output:<br><textarea id="output" name="w3review" rows="2" cols="100" spellcheck="false"></textarea>
</body></html>