Como escapar de uma string JSON contendo caracteres de nova linha usando JavaScript?


166

Eu tenho que formar uma string JSON na qual um valor está tendo um novo caractere de linha. Isso deve ser evitado e postado usando a chamada AJAX. Qualquer um pode sugerir uma maneira de escapar da string com JavaScript. Eu não estou usando jQuery.


1
Tentei escapar do novo caractere de linha \ n para \\ n. Está funcionando bem. Mas estou procurando por qualquer biblioteca JS que possa fazer isso para todos os caracteres de escape.
Srikant

1
Por que você precisa escapar das novas linhas dentro do JSON? Como esses valores estão sendo decodificados quando são usados, porque a solução apropriada é usar a função de codificação relacionada.
ZzzzBov 04/10/2013

Passei 6 horas tentando todo tipo de coisa com toneladas de variações, apenas para descobrir uma pequena barra adicional que faria tudo funcionar como mágica. As coisas que eu achava difícil duravam 5 minutos ... a coisa que eu pensava que era dada se tornava impossível. .omg
Muhammad Umer

1
Quando você usa chamadas Ajax com php-db-saving do lado do servidor, basta usar a função php addlashes () para convertê-lo. Com esta solução, você só tem um lugar para converter e é mais limpo que as linhas de substituição de javascript.
Marcel Ennix

Respostas:


134

Leve o seu JSON e .stringify()ele. Em seguida, use o .replace()método e substitua todas as ocorrências de \npor \\n.

EDITAR:

Tanto quanto eu sei, não há bibliotecas JS conhecidas para escapar de todos os caracteres especiais em uma string. Mas você pode encadear o .replace()método e substituir todos os caracteres especiais 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. 

Mas isso é muito desagradável, não é? Entre na beleza das funções, pois elas permitem que você divida o código em pedaços e mantenha o fluxo principal do seu script limpo e livre de 8 .replace()chamadas em cadeia . Então, vamos colocar essa funcionalidade em uma função chamada escapeSpecialChars(),. Vamos ir em frente e anexá-lo ao prototype chaindo Stringobjeto, de modo que podemos chamar escapeSpecialChars()diretamente sobre objetos String.

Igual a:

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

Depois de definirmos essa função, o corpo principal do nosso código é tão simples quanto isto:

var myJSONString = JSON.stringify(myJSON);
var myEscapedJSONString = myJSONString.escapeSpecialChars();
// myEscapedJSONString is now ready to be POST'ed to the server

3
Obrigado alex. Eu tenho que fazer isso para todos os caracteres de escape, certo? Existe alguma biblioteca JS para fazer isso?
Srikant

2
Esta é a função exata que resolveu meu problema String.prototype.escapeSpecialChars = function () {retorne this.replace (/ \\ / g, "\\\\"). substituir (/ \ n / g, "\\ n"). substituir (/ \ r / g, "\\ r"). substituir (/ \ t / g, "\\ t"). substituir (/ \ f / g, "\\ f"). substituir (/ "/ g," \\\ ""). substituir (/ '/ g, "\\\'"). substituir (/ \ & / g, "\\ &"); }
Srikant

10
Conforme observado na resposta do usuário667073, existem alguns erros nesta solução. Veja json.org - & e ' não deve ser escapado.
Alexander Klimetschek

5
Eu tive que votar menos, pois as expressões regulares parecem estar erradas. Tentei usá-lo, mas tive que corrigir as expressões regulares removendo uma das barras, por exemplo: / \\ n / g deveria ser / \ n / g. Consulte "Caracteres não imprimíveis" neste link para obter detalhes - Informações sobre o RegExp
b01

1
e quanto a si mesmo? isso também deveria ser evitado?
arash Moeen

65

Conforme sugerido pelo usuário667073, exceto reordenar a substituição da barra invertida primeiro e corrigir a substituição da cotação

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');
};

3
Você não precisa fazer tudo isso. Apenas barra invertida, nova linha, avanço de linha e as duas aspas. E está faltando: aspas simples Line separator \u2028e Paragraph separator \u2029. Re
Ariel

1
Bom, mas por que os colchetes são necessários e não: 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
perfeito. a resposta aceita (acima desta) simplesmente não funciona. usando nodeJS.
Yossi Shasho

Eu recebo este erro:Uncaught SyntaxError: Unexpected token \ in JSON at position 2
Pathros

32

Como você, estive analisando vários comentários e postando para substituir caracteres de escape especiais no meu JSON, que contém objetos html dentro dele.

Meu objetivo é remover os caracteres especiais no objeto JSON e também renderizar o html que está dentro do objeto json.

Aqui está o que eu fiz e espero que seja muito simples de usar.

Primeiro, fiz JSON.stringify meu objeto json e JSON.parse o resultado.

Por exemplo:

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

E resolve o meu problema e feito usando Javascript puro.


4
Este é definitivamente o caminho a percorrer
Oz Lodriguez

1
Este é definitivamente o caminho a seguir.
MartianE

1
Este é definitivamente vai quebrar em objetos grandes e complexos com stackoverflowerro
AaA

1
tente JSON.parse(JSON.stringify($("body")))em um arquivo html com body e algumas poucas tabelas. $ ("body") é um objeto javascript, mas o stringify falhará ao analisá-lo.
AaA

Vou verificar sua consulta e reverter.
Balasubramani M

24

Receio dizer que a resposta dada por Alex é incorreta, para dizer o mínimo:

  • Alguns personagens que Alex tenta escapar não precisam ser escapados (como & e ');
  • \ b não é o caractere de backspace, mas uma correspondência de limite de palavras
  • Os caracteres que precisam ser escapados não são manipulados.

Esta função

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 uma aproximação melhor.


5
na verdade, você deve alterar a ordem para substituir as barras invertidas antes das aspas duplas, ou você terminará com \\\\ ". Além disso, a linha de cotação deve ser .replace (/ [\"] / g, '\\\ "')
Ryan

10

Uma pequena atualização para aspas 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);

7

este é um post antigo. mas ainda pode ser útil para quem usa angular.fromJson e JSON.stringify. escape () está obsoleto. use isso em vez disso,

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


O stringify já faz todo o escape para você - estou curioso por que não usar isso? git.io/vglq7
Ben Davis

5

Há também um segundo parâmetro no JSON.stringify. Portanto, uma solução mais elegante seria:

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

5

Esta é uma pergunta antiga, mas a solução não funcionou bem para mim, pois não resolveu todos os casos. Finalmente encontrei uma resposta que fez o trabalho aqui

Vou postar minha solução combinada de usar o escape e codificar o 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);
}

Talvez remova as aspas duplas ao redor da string depois também? escape = (string) -> JSON.stringify(string)[1...-1]
Radek


3

Use json_encode () se o idioma do script do servidor for PHP, json_encode()escapa da nova linha e de outros tokens inesperados para você (se não estiver usando o PHP, procure uma função semelhante para a sua linguagem de script)

então use $.parseJSON()no seu JavaScript, pronto!


Se passar dados de php para javascript como string JSON, verifique esta resposta - escape duplo, me ajudou a passar JSON.parse e converter json string em 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 codificação dupla
Vladimir Vukanac

2

Eu tive a mesma situação em uma das minhas chamadas do Ajax, onde JSONestava lançando um erro devido à nova linha no campo Textarea. A solução dada aqui não funcionou para mim. Então eu usei a .escapefunção Javascript e funcionou bem. Em seguida, para recuperar o valor de JSON, eu simplesmente escapei usando .unescape.


Usando chamadas Ajax, prefiro usar a função php newStr = adicionalashes (str) e salve no db. Então eu não tenho que converter em javascript- (cliente) -side. Com esta solução, você precisa de apenas um lugar para converter as barras. Estou muito feliz com esta solução.
Marcel Ennix

2

Eu usei o jQuery.serialize () embutido para extrair o valor de uma área de texto para codificar a entrada. A parte pro é que você não precisa substituir todos os caracteres especiais por conta própria e eu também mantenho as novas linhas e escapa html. Para que a serialização funcione, parece que o campo de entrada precisa ter um atributo name e também adiciona o mesmo atributo à string de escape que precisa ser substituída. Pode não ser o que você está procurando, mas funciona para mim.

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

1

Ao usar qualquer forma de Ajax, a documentação detalhada para o formato das respostas recebidas do servidor CGI parece estar faltando na Web. Algumas entradas aqui apontam que as novas linhas nos dados retornados de texto ou json devem ser escapadas para evitar loops infinitos (travamentos) na conversão JSON (possivelmente criada ao lançar uma exceção não capturada), seja feita automaticamente pelo jQuery ou manualmente usando o sistema Javascript ou a análise JSON da biblioteca chamadas.

Em cada caso em que os programadores postam esse problema, são apresentadas soluções inadequadas (na maioria das vezes substituindo \ n por \\ n no lado de envio) e o problema é descartado. Sua inadequação é revelada ao passar valores de cadeia que incorporam acidentalmente seqüências de escape de controle, como nomes de caminhos do Windows. Um exemplo é "C: \ Chris \ Roberts.php", que contém os caracteres de controle ^ c e ^ r, que podem causar a conversão JSON da string {"file": "C: \ Chris \ Roberts.php"} para loop para sempre. Uma maneira de gerar esses valores é deliberadamente tentar passar mensagens de aviso e erro de PHP do servidor para o cliente, uma idéia razoável.

Por definição, o Ajax usa conexões HTTP nos bastidores. Essas conexões passam dados usando GET e POST, os quais requerem codificação de dados enviados para evitar sintaxe incorreta, incluindo caracteres de controle.

Isso dá uma dica suficiente para construir o que parece ser uma solução (ele precisa de mais testes): usar o código bruto no lado do PHP (envio) para codificar os dados e desmarcar no lado do Javascript (recebimento) para decodificar os dados. Em alguns casos, você os aplicará a cadeias de texto inteiras, em outros casos, aplicará-as apenas a valores dentro do JSON.

Se essa idéia estiver correta, exemplos simples podem ser construídos para ajudar programadores de todos os níveis a resolver esse problema de uma vez por todas.


0

Parece que este é realmente um post antigo :-) Mas, pessoal, a melhor solução que eu tenho para isso, ser 100% que ele funciona sem código complicado, é usar as duas funções de codificação / decodificação para base64. Estes são atob () e btoa (). De longe, a maneira mais fácil e melhor, não precisa se preocupar se você perdeu algum personagem para escapar.

George


Desde que eu vim com a mesma solução. Gostaria de saber se alguém poderia esclarecer essa solução e se existem algumas advertências ocultas. Obrigado.
Mahish 19/07/2018

0

Se seus Googles continuarem aterrando você aqui e sua API lançar erros, a menos que suas aspas duplas JSON sejam escapadas ( "{\"foo\": true}"), tudo que você precisa fazer é especificar duas vezes, por exemplo,JSON.stringify(JSON.stringify(bar))


-1

Use encodeURIComponent () para codificar a sequência.

Por exemplo. var myEscapedJSONString = encodeURIComponent (JSON.stringify (myJSON));

Você não precisa decodificá-lo, pois o servidor da Web faz o mesmo automaticamente.


-8

Nunca use expressões regulares (quero dizer, como nunca). A melhor e mais eficaz maneira:

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;
};

Você não pode dizer: "Nunca use expressões regulares (quero dizer, como nunca)". Toda ferramenta serve ao seu propósito.
zstate 14/02

Sua resposta é válida, você acabou de expressá-la de uma maneira altamente opinativa, o que pode criar confusão, especialmente para os juniores.
zstate 17/02

As expressões regulares do @oncode são incrivelmente inúteis, não importa como e quando usá-las. Isso só leva a um comportamento indefinido e desperdiça o tempo da CPU.
Alek Depler 22/02
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.