¿Cómo escapar de una cadena JSON que contiene caracteres de nueva línea usando JavaScript?

166

Tengo que formar una cadena JSON en la que un valor tenga un nuevo carácter de línea. Esto tiene que ser escapado y luego publicado usando la llamada AJAX. ¿Alguien puede sugerir una forma de escapar de la cadena con JavaScript? No estoy usando jQuery.

Srikant
fuente
1
Intenté escapar del nuevo carácter de línea \ n a \\ n. Esta funcionando bien Pero estoy buscando cualquier biblioteca JS que pueda hacer esto para todos los caracteres de escape.
Srikant
1
¿Por qué necesitas escapar de las nuevas líneas dentro del JSON? Cómo se decodifican estos valores cuando se usan, porque la solución adecuada es usar la función de codificación relacionada.
zzzzBov
Pasé 6 horas probando todo tipo de cosas con toneladas de variaciones solo para descubrir que una pequeña barra adicional haría que todo funcionara como magia, las cosas que pensé que eran difíciles tomaron como 5 minutos ... lo que pensé que se dio se volvió imposible. .omg
Muhammad Umer
1
Cuando use llamadas Ajax con php-db-saving del lado del servidor, solo use la función php addlashes () para convertirlo. Con esta solución, solo tiene un lugar para convertir y es más limpio que las líneas de reemplazo de javascript.
Marcel Ennix

Respuestas:

134

Toma tu JSON y .stringify()eso. Luego use el .replace()método y reemplace todas las apariciones de \ncon \\n.

EDITAR:

Hasta donde yo sé, no hay bibliotecas JS conocidas para escapar de todos los caracteres especiales en una cadena. Pero, podría encadenar el .replace()método y reemplazar todos los caracteres especiales como este:

var myJSONString = JSON.stringify(myJSON);
var myEscapedJSONString = myJSONString.replace(/\\n/g, "\\n")
                                      .replace(/\\'/g, "\\'")
                                      .replace(/\\"/g, '\\"')
                                      .replace(/\\&/g, "\\&")
                                      .replace(/\\r/g, "\\r")
                                      .replace(/\\t/g, "\\t")
                                      .replace(/\\b/g, "\\b")
                                      .replace(/\\f/g, "\\f");
// myEscapedJSONString is now ready to be POST'ed to the server. 

Pero eso es bastante desagradable, ¿no? Ingrese la belleza de las funciones, ya que le permiten dividir el código en pedazos y mantener el flujo principal de su script limpio y libre de 8 .replace()llamadas encadenadas . Pongamos esa funcionalidad en una función llamada escapeSpecialChars(),. Vamos a seguir adelante y adjuntarlo a la prototype chaindel Stringobjeto, por lo que podemos llamar escapeSpecialChars()directamente sobre los objetos de cadena.

Al igual que:

String.prototype.escapeSpecialChars = function() {
    return this.replace(/\\n/g, "\\n")
               .replace(/\\'/g, "\\'")
               .replace(/\\"/g, '\\"')
               .replace(/\\&/g, "\\&")
               .replace(/\\r/g, "\\r")
               .replace(/\\t/g, "\\t")
               .replace(/\\b/g, "\\b")
               .replace(/\\f/g, "\\f");
};

Una vez que hemos definido esa función, el cuerpo principal de nuestro código es tan simple como esto:

var myJSONString = JSON.stringify(myJSON);
var myEscapedJSONString = myJSONString.escapeSpecialChars();
// myEscapedJSONString is now ready to be POST'ed to the server
Alex
fuente
3
Gracias alex. Tengo que hacer esto para todos los personajes de escape, ¿verdad? ¿Hay alguna biblioteca JS para hacer esto?
Srikant
2
Esta es la función exacta que resolvió mi problema String.prototype.escapeSpecialChars = function () {return this.replace (/ \\ / g, "\\\\"). reemplazar (/ \ n / g, "\\ n"). reemplace (/ \ r / g, "\\ r"). reemplace (/ \ t / g, "\\ t"). reemplazar (/ \ f / g, "\\ f"). reemplace (/ "/ g," \\\ ""). reemplace (/ '/ g, "\\\'"). reemplazar (/ \ & / g, "\\ &"); }
Srikant
10
Como se señaló en la respuesta del usuario 667073, hay algunos errores en esta solución. Ver json.org - & y ' no se deben escapar.
Alexander Klimetschek
55
Tuve que rechazar esto porque las expresiones regulares parecen estar equivocadas. Intenté usarlo, pero tuve que arreglar las expresiones regulares quitando una de las barras, por ejemplo: / \\ n / g debería ser / \ n / g. Consulte "Caracteres no imprimibles" en este enlace para obtener más información
b01
1
¿Qué pasa con \ sí mismo? ¿debería eso también escapar?
arash moeen
65

Según el usuario 667073 sugerido, excepto reordenar el reemplazo de la barra diagonal inversa primero y arreglar el reemplazo de la cotización

escape = function (str) {
  return str
    .replace(/[\\]/g, '\\\\')
    .replace(/[\"]/g, '\\\"')
    .replace(/[\/]/g, '\\/')
    .replace(/[\b]/g, '\\b')
    .replace(/[\f]/g, '\\f')
    .replace(/[\n]/g, '\\n')
    .replace(/[\r]/g, '\\r')
    .replace(/[\t]/g, '\\t');
};
Ryan
fuente
3
No tienes que hacer todo esto. Solo barra invertida, nueva línea, salto de línea y las dos comillas. Y falta: comilla simple Line separator \u2028y Paragraph separator \u2029. Ref: es5.github.io/#x7.3
Ariel
1
Bien, pero ¿por qué son necesarios los corchetes y no: escape = function (str) {return str .replace (/ \\ / g, '\\\\') .replace (/ \ "/ g, '\\\ "') .replace (/ \ // g,' \\ / ') .replace (/ \ b / g,' \\ b ') .replace (/ \ f / g,' \\ f ') .replace (/ \ n / g, '\\ n') .replace (/ \ r / g, '\\ r') .replace (/ \ t / g, '\\ t'); };
Johann Echavarria
3
Perfecto. la respuesta aceptada (arriba de esta) simplemente no funciona. usando nodeJS.
Yossi Shasho
Me sale este error:Uncaught SyntaxError: Unexpected token \ in JSON at position 2
Pathros
32

Al igual que usted, he estado buscando varios comentarios y publicaciones para reemplazar los caracteres de escape especiales en mi JSON que contiene objetos HTML dentro de eso.

Mi objetivo es eliminar los caracteres especiales en el objeto JSON y también renderizar el html que está dentro del objeto json.

Esto es lo que hice y espero que sea muy fácil de usar.

Primero hice JSON.stringify mi objeto json y JSON.parse el resultado.

Por ejemplo:

JSON.parse(JSON.stringify(jsonObject));

Y resuelve mi problema y termina usando Pure Javascript.

Balasubramani M
fuente
44
Este es definitivamente el camino a seguir
Oz Lodriguez
1
¡Este es definitivamente el camino a seguir!
MartianE
1
Esto definitivamente se romperá en objetos complejos y grandes con stackoverflowerror
AaA
1
intente JSON.parse(JSON.stringify($("body")))en un archivo html con body y algunas tablas. $ ("body") es un objeto javascript pero stringify fallará al analizarlo.
AaA
Revisaré su consulta y la revertiré.
Balasubramani M
24

Me temo decir que la respuesta dada por Alex es bastante incorrecta, por decirlo suavemente:

  • No es necesario que algunos personajes que Alex intenta escapar (como & y ');
  • \ b no es en absoluto el carácter de retroceso sino más bien una coincidencia de límite de palabra
  • Los caracteres necesarios para escapar no se manejan.

Esta función

escape = function (str) {
    // TODO: escape %x75 4HEXDIG ?? chars
    return str
      .replace(/[\"]/g, '\\"')
      .replace(/[\\]/g, '\\\\')
      .replace(/[\/]/g, '\\/')
      .replace(/[\b]/g, '\\b')
      .replace(/[\f]/g, '\\f')
      .replace(/[\n]/g, '\\n')
      .replace(/[\r]/g, '\\r')
      .replace(/[\t]/g, '\\t')
    ; };

Parece ser una mejor aproximación.

whaefelinger
fuente
55
en realidad, debe cambiar el orden para reemplazar las barras invertidas antes de las comillas dobles, o de lo contrario terminará con \\\\ ". También la línea de comillas debería ser .replace (/ [\"] / g, '\\\ "')
Ryan
10

Una pequeña actualización para comillas simples

function escape (key, val) {
    if (typeof(val)!="string") return val;
    return val      
        .replace(/[\\]/g, '\\\\')
        .replace(/[\/]/g, '\\/')
        .replace(/[\b]/g, '\\b')
        .replace(/[\f]/g, '\\f')
        .replace(/[\n]/g, '\\n')
        .replace(/[\r]/g, '\\r')
        .replace(/[\t]/g, '\\t')
        .replace(/[\"]/g, '\\"')
        .replace(/\\'/g, "\\'"); 
}

var myJSONString = JSON.stringify(myJSON,escape);
Akash Dhawale
fuente
7

Esta es una publicación vieja. pero aún puede ser útil para aquellos que usan angular.fromJson y JSON.stringify. escape () está en desuso. use esto en su lugar,

var uri_enc = encodeURIComponent(uri); //before you post the contents
var uri_dec = decodeURIComponent(uri_enc); //before you display/use the contents.

ref http://www.w3schools.com/jsref/jsref_decodeuricomponent.asp

Sam
fuente
stringify ya se escapa por ti, tengo curiosidad por qué no usar eso. git.io/vglq7
Ben Davis
5

También hay un segundo parámetro en JSON.stringify. Entonces, la solución más elegante sería:

function escape (key, val) {
    if (typeof(val)!="string") return val;
    return val
      .replace(/[\"]/g, '\\"')
      .replace(/[\\]/g, '\\\\')
      .replace(/[\/]/g, '\\/')
      .replace(/[\b]/g, '\\b')
      .replace(/[\f]/g, '\\f')
      .replace(/[\n]/g, '\\n')
      .replace(/[\r]/g, '\\r')
      .replace(/[\t]/g, '\\t')
    ; 
}

var myJSONString = JSON.stringify(myJSON,escape);
Krunoslav Djakovic
fuente
5

Esta es una vieja pregunta, pero la solución no funcionó bien para mí, ya que no resolvió todos los casos. Finalmente encontré una respuesta que hizo el trabajo aquí

Publicaré mi solución combinada de ambos usando escape y codificar componente uri:

// implement JSON stringify serialization
JSON.stringify = JSON.stringify || function (obj) {
    var t = typeof (obj);
    if (t != "object" || obj === null) {
        // simple data type
        if (t == "string") obj = '"'+obj+'"';
        return String(obj);
    }
    else {
        // recurse array or object
        var n, v, json = [], arr = (obj && obj.constructor == Array);
        for (n in obj) {
            v = obj[n]; t = typeof(v);
            if (t == "string") v = '"'+v+'"';
            else if (t == "object" && v !== null) v = JSON.stringify(v);
            json.push((arr ? "" : '"' + n + '":') + String(v));
        }
        var rawString = (arr ? "[" : "{") + String(json) + (arr ? "]" : "}");
       return rawString;
    }
};
function escape (key, val) {
    if (typeof(val)!="string") return val;

    var replaced = encodeURIComponent(val);
    return replaced;
}

JSON.stringifyEscaped = function(obj){
    return JSON.stringify(obj,escape);
}
Mitzi
fuente
¿Quizás también elimine las comillas dobles alrededor de la cadena después? escape = (string) -> JSON.stringify(string)[1...-1]
Radek
3

Es mejor usar JSON.parse(yourUnescapedJson);

Mohit Vachhani
fuente
3

Use json_encode () si su idioma de scripting del lado del servidor es PHP, json_encode()escapa de la nueva línea y otros tokens inesperados por usted (si no usa PHP, busque una función similar para su lenguaje de scripting)

a continuación, utilizar $.parseJSON()en su JavaScript, hecho!

avngr
fuente
Si pasa datos de php a javascript como una cadena JSON, verifique esta respuesta: doble escape, me ayudó a pasar JSON.parse y convertir la cadena json a objeto. <script> windows.data_from_php = <?php echo json_encode(json_encode($arrayOrObjToJs)); ?>; var phpData = JSON.parse(windows.data_from_php); </script> php JSON.parse doble codificación
Vladimir Vukanac
2

Tuve la misma situación en una de mis llamadas de Ajax, donde JSONestaba arrojando un error debido a la nueva línea en el campo Textarea. La solución dada aquí no funcionó para mí. Así que usé la .escapefunción de Javascript y funcionó bien. Luego, para recuperar el valor JSON, simplemente escapé usando .unescape.

Anubhav Trivedi
fuente
Usando llamadas Ajax, prefiero usar la función php newStr = addlashes (str), luego guardar en db. Así que no tengo que convertir en javascript- (client) -side. Con esta solución, solo necesita un lugar para convertir las barras. Estoy muy contento con esta solución.
Marcel Ennix
2

I utilizado el construido en jQuery.serialize () para extraer el valor de un área de texto a urlencode la entrada. La parte profesional es que no tiene que buscar reemplazar cada carácter especial por su cuenta y también mantengo las nuevas líneas y escapa html. Para que la serialización funcione, parece que el campo de entrada debe tener un atributo de nombre y también agrega el mismo atributo a la cadena escapada que debe reemplazarse. Puede que no sea lo que estás buscando, pero funciona para mí.

var myinputfield = jQuery("#myinputfield"); 
var text = myinputfield.serialize();
text = text.replace(myinputfield.attr('name') + '=','');
Janspeed
fuente
1

Cuando se utiliza cualquier forma de Ajax, la documentación detallada para el formato de las respuestas recibidas del servidor CGI parece faltar en la Web. Algunas entradas aquí señalan que las nuevas líneas en el texto devuelto o en los datos json deben escaparse para evitar bucles infinitos (bloqueos) en la conversión JSON (posiblemente creada al lanzar una excepción no detectada), ya sea que se realice automáticamente mediante jQuery o manualmente usando el sistema Javascript o el análisis JSON de la biblioteca llamadas.

En cada caso donde los programadores publican este problema, se presentan soluciones inadecuadas (la mayoría de las veces reemplazando \ n por \\ n en el lado de envío) y el asunto se descarta. Su insuficiencia se revela al pasar valores de cadena que incrustan accidentalmente secuencias de escape de control, como nombres de ruta de Windows. Un ejemplo es "C: \ Chris \ Roberts.php", que contiene los caracteres de control ^ c y ^ r, que pueden provocar la conversión JSON de la cadena {"archivo": "C: \ Chris \ Roberts.php"} a bucle para siempre. Una forma de generar tales valores es deliberadamente intentar pasar mensajes de advertencia y error de PHP del servidor al cliente, una idea razonable.

Por definición, Ajax usa conexiones HTTP detrás de escena. Dichas conexiones pasan datos utilizando GET y POST, los cuales requieren codificar los datos enviados para evitar una sintaxis incorrecta, incluidos los caracteres de control.

Esto da una pista suficiente para construir lo que parece ser una solución (necesita más pruebas): usar el código rawurlen en el lado PHP (envío) para codificar los datos y no escapar en el lado Javascript (recepción) para decodificar los datos. En algunos casos, los aplicará a cadenas de texto completas, en otros casos los aplicará solo a valores dentro de JSON.

Si esta idea resulta ser correcta, se pueden construir ejemplos simples para ayudar a los programadores en todos los niveles a resolver este problema de una vez por todas.

David Spector
fuente
0

Parece que esta es una publicación antigua realmente :-) Pero chicos, la mejor solución que tengo para esto, para ser 100% que funciona sin código complicado, es usar ambas funciones de codificación / decodificación a base64. Estos son atob () y btoa (). Con mucho, la forma más fácil y mejor, no hay que preocuparse si se perdió algún personaje para escapar.

Jorge

Giorgoc
fuente
Desde que se me ocurrió la misma solución. Me pregunto si alguien podría aclarar esta solución y si hay algunas advertencias ocultas. Gracias.
mahish
0

Si sus Google continúan aterrizando aquí y su api arroja errores a menos "{\"foo\": true}"que se escapen sus comillas dobles JSON ( ), todo lo que necesita hacer es stringificar dos veces, por ejemploJSON.stringify(JSON.stringify(bar))

Avolition
fuente
-1

Use encodeURIComponent () para codificar la cadena.

P.ej. var myEscapedJSONString = encodeURIComponent (JSON.stringify (myJSON));

No necesita decodificarlo, ya que el servidor web automáticamente hace lo mismo.

Sanju Kaniyamattam
fuente
-8

Nunca use expresiones regulares (quiero decir, nunca como nunca). La mejor y más efectiva forma:

String.prototype.escapeJSON = function() {
    var result = "";
    for (var i = 0; i < this.length; i++)
    {
        var ch = this[i];
        switch (ch)
        {
            case "\\": ch = "\\\\"; break;
            case "\'": ch = "\\'"; break;
            case "\"": ch = '\\"'; break;
            case "\&": ch = "\\&"; break;
            case "\t": ch = "\\t"; break;
            case "\n": ch = "\\n"; break;
            case "\r": ch = "\\r"; break;
            case "\b": ch = "\\b"; break;
            case "\f": ch = "\\f"; break;
            case "\v": ch = "\\v"; break;
            default: break;
        }

        result += ch;
    }

    return result;
};
Alek Depler
fuente
No puedes decir: "Nunca uses expresiones regulares (quiero decir, como nunca)". Cada herramienta cumple su propósito.
zstate
Su respuesta es válida, simplemente la expresó de una manera muy obstinada, lo que podría crear confusión, especialmente para los jóvenes.
zstate
Las expresiones regulares de @oncode son increíblemente inútiles, sin importar cómo y cuándo usarlas. Solo conduce a un comportamiento indefinido y a perder tiempo de CPU.
Alek Depler