Escape string w kontekście eval z JSON.stringify

Nov 13 2020

Po pierwsze: wiem, że pytań związanych z ucieczką jest wiele, ale jak dotąd nie znalazłem ogólnie działającej odpowiedzi. Powiedzmy, że mam tę prostą funkcję zabawki do demonstracji:

function f(somePOJO) {
  var s = eval("'" + JSON.stringify(somePOJO) + "';"); // for demonstration only
  return JSON.parse(s);
}
const clone = f({a: 1, b: "c"});

Biorąc pod uwagę literał obiektu, taki jak {a: 1, b: "c"}(POJO), fpowinien zwrócić jego „klon”. (Zwróć uwagę, że tak naprawdę nie używam tego podejścia do klonowania lub podobnego i mam świadomość, że evaljest to złe, a także, że nie jest to nawet tutaj potrzebne, służy tylko do zademonstrowania uciekającego problemu!)

Działa to dobrze, ale tylko wtedy, gdy wartości POJO nie zawierają rozszerzenia '. Teraz oczywiście mogłem uciec od JSON, używając czegoś takiego jak JSON.stringify(somePOJO).replace(/'/g, "\\'"). Działa to, jeśli wartości POJO zawierają ', ale nie, jeśli zawierają \\'. A to tworzy spiralę ucieczki ...

Czy w ogóle istnieje rozwiązanie tego problemu?

Odpowiedzi

1 traktor Nov 13 2020 at 14:01

Funkcja ucieczki, która zachowuje ciąg JSON przez ocenę przez evalfunkcję, kompilator JavaScript w pewnych okolicznościach lub przez JSON.parsefunkcję jest w rzeczywistości JSON.stringify. Ta JSONmetoda z przyjemnością określi wartości łańcuchowe, a nie tylko typy danych obiektu.

function f(somePOJO) {
  var s = eval( JSON.stringify(JSON.stringify(somePOJO)) );
  return JSON.parse(s);
}
const obj = {a: 1, b: "c", d: "back\\, forward/"}
const clone = f(obj);
console.log(obj);
console.log(clone);

Powodem, dla którego nie należy do escape/encodeURI/encodeURIComponentrodziny funkcji, jest to, że służą one do ucieczki znaków do umieszczenia w adresach URL, podczas gdy ten przypadek dotyczy znaków ucieczki, które mają być przeanalizowane przez parser JavaScipt.

W większości przypadków, szczególnie w celu przeanalizowania tekstu JSON przy użyciu JSON.parse, powtórne dodawanie stringów do tekstu JSON i dwukrotne analizowanie go jest po prostu niepotrzebne.

Trochę interesujący akademicki teraz, ale przed wprowadzeniem JSONdo Javascript, można było określić ciąg znaków poprzez seryjną kontrolę jego znaków i ukośnika odwrotnego przed ukośnikiem odwrotnym, co najmniej jednego rodzaju cudzysłowów i unikodowych kodów kontrolnych - w opublikowanym pytaniu może brakować części o konieczności ucieczki przed znakami ukośnika odwrotnego oraz cudzysłowami.