Como faço para lidar com novas linhas no JSON?

Gerei algum JSON e estou tentando puxá-lo para um object em JavaScript. Eu continuo recebendo erros. Aqui está o que eu tenho:

var data = '{"count" : 1, "stack" : "sometext\n\n"}'; var dataObj = eval('('+data+')'); 

Isso me dá um erro:

 unterminated string literal 

Com JSON.parse(data) , vejo mensagens de erro semelhantes: ” Unexpected token ↵ ” no Chrome e ” unterminated string literal ” no Firefox e no IE.

Quando eu tiro o \n depois de sometext o erro desaparece em ambos os casos. Não consigo descobrir por que \n eval e JSON.parse falham.

   

Eu acho que isso é o que você quer:

 var data = '{"count" : 1, "stack" : "sometext\\n\\n"}'; 

(Você precisa escaping do “\” na sua string (transformando-o em um double – “\”), caso contrário, ele se tornará uma nova linha na fonte JSON, não os dados JSON.)

Você precisará ter uma function que substitua \n para \\n caso os data não sejam um literal de string.

 function jsonEscape(str) { return str.replace(/\n/g, "\\\\n").replace(/\r/g, "\\\\r").replace(/\t/g, "\\\\t"); } var data = '{"count" : 1, "stack" : "sometext\n\n"}'; var dataObj = JSON.parse(jsonEscape(data)); 

Os dataObj resultantesObj serão

 Object {count: 1, stack: "sometext\n\n"} 

De acordo com as especificações: http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf

 A string is a sequence of Unicode code points wrapped with quotation marks (U+0022). All characters may be placed within the quotation marks except for the characters that must be escaped: quotation mark (U+0022), reverse solidus (U+005C), and the control characters U+0000 to U+001F. There are two-character escape sequence representations of some characters. 

Então você não pode passar códigos 0x0A ou 0x0C diretamente. É proibido! Especula sugere usar seqüências de escape para alguns códigos bem definidos de U+0000 para U+001F :

 \f represents the form feed character (U+000C). \n represents the line feed character (U+000A). 

Como a maioria das linguagens de programação usa \ para aspas, você deve escaping da syntax de escape (double-escape – uma vez para linguagem / plataforma, uma vez para o próprio Json):

 jsonStr = "{ \"name\": \"Multi\\nline.\" }"; 

Você pode simplesmente escaping da sua string no servidor ao escrever o valor do campo json e anulá-lo ao recuperar o valor no navegador do cliente, por exemplo.

A implementação do javascript de todos os principais navegadores tem o comando unescape.

Exemplo: no servidor:

 response.write "{""field1"":""" & escape(RS_Temp("textField")) & """}" 

no navegador:

 document.getElementById("text1").value = unescape(jsonObject.field1) 

Você pode querer olhar para esta function C # para escaping da string:

http://www.aspcode.net/C-encode-a-string-for-JSON-JavaScript.aspx

 public static string Enquote(string s) { if (s == null || s.Length == 0) { return "\"\""; } char c; int i; int len = s.Length; StringBuilder sb = new StringBuilder(len + 4); string t; sb.Append('"'); for (i = 0; i < len; i += 1) { c = s[i]; if ((c == '\\') || (c == '"') || (c == '>')) { sb.Append('\\'); sb.Append(c); } else if (c == '\b') sb.Append("\\b"); else if (c == '\t') sb.Append("\\t"); else if (c == '\n') sb.Append("\\n"); else if (c == '\f') sb.Append("\\f"); else if (c == '\r') sb.Append("\\r"); else { if (c < ' ') { //t = "000" + Integer.toHexString(c); string t = new string(c,1); t = "000" + int.Parse(tmp,System.Globalization.NumberStyles.HexNumber); sb.Append("\\u" + t.Substring(t.Length - 4)); } else { sb.Append(c); } } } sb.Append('"'); return sb.ToString(); } 

Oi eu usei essa function para tira nova linha ou outros caracteres em dados para analisar dados JSON:

 function normalize_str($str) { $invalid = array('Š'=>'S', 'š'=>'s', 'Đ'=>'Dj', 'đ'=>'dj', 'Ž'=>'Z', 'ž'=>'z', 'Č'=>'C', 'č'=>'c', 'Ć'=>'C', 'ć'=>'c', 'À'=>'A', 'Á'=>'A', 'Â'=>'A', 'Ã'=>'A', 'Ä'=>'A', 'Å'=>'A', 'Æ'=>'A', 'Ç'=>'C', 'È'=>'E', 'É'=>'E', 'Ê'=>'E', 'Ë'=>'E', 'Ì'=>'I', 'Í'=>'I', 'Î'=>'I', 'Ï'=>'I', 'Ñ'=>'N', 'Ò'=>'O', 'Ó'=>'O', 'Ô'=>'O', 'Õ'=>'O', 'Ö'=>'O', 'Ø'=>'O', 'Ù'=>'U', 'Ú'=>'U', 'Û'=>'U', 'Ü'=>'U', 'Ý'=>'Y', 'Þ'=>'B', 'ß'=>'Ss', 'à'=>'a', 'á'=>'a', 'â'=>'a', 'ã'=>'a', 'ä'=>'a', 'å'=>'a', 'æ'=>'a', 'ç'=>'c', 'è'=>'e', 'é'=>'e', 'ê'=>'e', 'ë'=>'e', 'ì'=>'i', 'í'=>'i', 'î'=>'i', 'ï'=>'i', 'ð'=>'o', 'ñ'=>'n', 'ò'=>'o', 'ó'=>'o', 'ô'=>'o', 'õ'=>'o', 'ö'=>'o', 'ø'=>'o', 'ù'=>'u', 'ú'=>'u', 'û'=>'u', 'ý'=>'y', 'ý'=>'y', 'þ'=>'b', 'ÿ'=>'y', 'Ŕ'=>'R', 'ŕ'=>'r', "`" => "'", "´" => "'", '"' => ',', '`' => "'", '´' => "'", '"' => '\"', '"' => "\"", '´' => "'", "’" => "'", "{" => "", "~" => "", "–" => "-", "'" => "'"," " => " "); $str = str_replace(array_keys($invalid), array_values($invalid), $str); $remove = array("\n", "\r\n", "\r"); $str = str_replace($remove, "\\n", trim($str)); //$str = htmlentities($str,ENT_QUOTES); return htmlspecialchars($str); } echo normalize_str($lst['address']); 

Eu encontrei esse problema ao fazer uma class no PHP4 para emular json_encode (disponível em PHP5). Aqui está o que eu criei:

 class jsonResponse { var $response; function jsonResponse() { $this->response = array('isOK'=>'KO','msg'=>'Undefined'); } function set($isOK, $msg) { $this->response['isOK'] = ($isOK) ? 'OK' : 'KO'; $this->response['msg'] = htmlentities($msg); } function setData($data=null) { if(!is_null($data)) $this->response['data'] = $data; elseif(isset($this->response['data'])) unset($this->response['data']); } function send() { header('Content-type: application/json'); echo '{"isOK":"'.$this->response['isOK'].'","msg":'.$this->parseString($this->response['msg']); if(isset($this->response['data'])) echo ',"data":'.$this->parseData($this->response['data']); echo '}'; } function parseData($data) { if(is_array($data)) { $parsed = array(); foreach ($data as $key=>$value) array_push($parsed, $this->parseString($key).':'.$this->parseData($value)); return '{'.implode(',', $parsed).'}'; } else return $this->parseString($data); } function parseString($string) { $string = str_replace("\\", "\\\\", $string); $string = str_replace('/', "\\/", $string); $string = str_replace('"', "\\".'"', $string); $string = str_replace("\b", "\\b", $string); $string = str_replace("\t", "\\t", $string); $string = str_replace("\n", "\\n", $string); $string = str_replace("\f", "\\f", $string); $string = str_replace("\r", "\\r", $string); $string = str_replace("\u", "\\u", $string); return '"'.$string.'"'; } } 

Eu segui as regras mencionadas aqui . Eu só usei o que eu precisava, mas acho que você pode adaptá-lo às suas necessidades na linguagem que você está usando. O problema no meu caso não era sobre novas linhas como eu pensava originalmente, mas sobre o fato de eu não ter escapado. Espero que isso impeça alguém da pequena dor de cabeça que eu tinha descoberto o que fiz de errado.