2008-09-03 9 views
193

He generado algunos JSON y estoy tratando de incorporarlo a un objeto en JavaScript. Sigo recibiendo errores Aquí es lo que tengo:¿Cómo manejo las nuevas líneas en JSON?

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

Esto me da un error:

unterminated string literal 

Con JSON.parse(data), aparecen mensajes de error similares: "Unexpected token ↵" en Chrome, y "unterminated string literal" en Firefox e IE.

Cuando saco el \n después de sometext el error desaparece en ambos casos. Parece que no puedo entender por qué el \n hace que eval y JSON.parse fallen.

+7

Pruebe usar un analizador json real en lugar de eval. – Eric

Respuesta

257

supongo que esto es lo que quiere:

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

(que necesita para escapar de la "\" en la cadena (convirtiéndolo en un doble - "\"), de lo contrario se convertirá en una nueva línea en . la fuente JSON, no los datos JSON)

+63

Esto es, por supuesto, correcto, pero me gustaría añadir la razón para tener que hacer esto: la especificación JSON en http://www.ietf.org/rfc/rfc4627.txt contiene esta oración en la sección 2.5: "Todos Los caracteres Unicode se pueden colocar entre comillas, excepto los caracteres que se deben escapar: comillas, solidus inverso y los caracteres de control (U + 0000 a U + 001F). " Como una nueva línea es un personaje de control, debe ser escapada. –

+0

Según www.json.org, JSON acepta la secuencia de control "\ n" en cadenas, y si prueba JSON.parse (['"a \\ na"']) [1] .charCodeAt(); eso mostrará 10 - que fue "Linefeed" la última vez que lo verifiqué. --- Por cierto: ¡Deja de gritar! – BlaM

2

Es posible que desee ver en esta función C# para escapar de la cadena:

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(); 
} 
+1

Deberías limpiar ese código un poco ... (No compila). –

+2

¿Por qué escapa '>'? – nothingisnecessary

19

Deberá tener una función que reemplace \n por \\n en caso de que data no sea una cadena literal.

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

resultante dataObj será

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

necesita escapar de sus caracteres de escape (es decir, '.replace (" \\ n "," \\\\ n ")') y también sugeriría usar regex para permitir el reemplazo de varias instancias (es decir '.replace (/ \ n/g, "\\\\ n") ') – musefan

+2

¿por qué necesita escapar de los caracteres de escape? Quiero decir algo como '.replace (" \ n "," \\ n ")' debería hacer bien el trabajo !! Por ejemplo, 'var test = [{" description ":" Alguna descripción sobre el producto. Esto puede ser texto de varias líneas. "}]; console.log (JSON.parse (test.replace (/ \ n/g, "\\ n"))); 'mostrará el objeto perfectamente bien en la consola del navegador como' [{"description": "Alguna descripción sobre el producto. \ nEsto puede ser texto multilínea. "}]' – Fr0zenFyr

+0

BTW, en el comentario anterior, la cadena JSON original tiene una nueva línea, que es eliminada por el formateador de comentarios de stackoverflow. Puede ver que la salida final después de reemplazar debe insertar una nueva línea char '\ n' en el valor. – Fr0zenFyr

0

me encontré con este problema al hacer una clase en PHP 4 para emular json_encode (disponible en PHP5). Esto es lo que ocurrió:

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.'"'; 
    } 
} 

he seguido las reglas lo mencionan here. Solo usé lo que necesitaba, pero creo que puedes adaptarlo a tus necesidades en el idioma que estás usando. El problema en mi caso no era sobre líneas nuevas como originalmente pensé, sino sobre/no haber escapado. Espero que esto evite que alguien más tenga el pequeño dolor de cabeza que tuve al descubrir lo que hice mal.

+0

Los 6 atajos para los caracteres de control especificados en json.org no son una lista exhaustiva de todos los caracteres de control. Como resultado, esta función podría generar JSON no válido. – Phil

2

Hola i utiliza esta función para despojar de nueva línea u otros caracteres en los datos para analizar JSON datos:

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', "`" => "'", "´" => "'", '"' => ',', '`' => "'", 
    '´' => "'", '"' => '\"', '"' => "\"", '´' => "'", "&acirc;€™" => "'", "{" => "", 
    "~" => "", "–" => "-", "'" => "'","  " => " "); 

    $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']); 
+6

En la mayoría de los idiomas, tiene mejores formas de quitar acentos de las cadenas Unicode que escribir su propia función de mapeo. Consulte esta pregunta para ver un ejemplo en python: http: // stackoverflow.com/questions/517923/what-is-the-best-way-to-remove-acentos-in-a-python-unicode-string – MiniQuark

+0

ya tenemos muchas formas de controlar los caracteres especiales en diferentes lenguajes. – ShivarajRH

+1

Eso es todo un poco malo para despojarlos en general. Mejor codificarlos como referencia de caracteres numéricos XML y luego decodificar en el extremo receptor. – Annarfych

2

Se podía escapar de su cadena en el servidor al escribir el valor del campo JSON y unescape cuando recuperando el valor en el navegador del cliente, por ejemplo.

La implementación de javascript de todos los principales navegadores tiene el comando de unescape.

Ejemplo: en el servidor:

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

en el navegador:

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

De acuerdo con las especificaciones: 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. 

lo que no puede pasar 0x0A o 0x0C códigos directamente. ¡Está prohibido! Spec sugiere utilizar secuencias de escape para algunos códigos bien definidos a partir de U+0000 a U+001F:

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

Como la mayoría de los lenguajes de programación utiliza \ por citar debe escapar sintaxis de escape (doble de escape - una vez para el lenguaje/plataforma, una vez para Json sí mismo):

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