我已经生成了一些JSON,我试图把它拉到一个对象在JavaScript。我总是出错。以下是我所拥有的:

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

这给了我一个错误:

unterminated string literal

使用JSON.parse(data),我看到类似的错误消息:在Chrome中“意外的令牌()”,在Firefox和IE中“未终止的字符串文字”。

当我在sometext后面去掉\n时,两种情况下错误都消失了。我似乎不明白为什么\n使eval和JSON。解析失败。


当前回答

根据规范,http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf:

字符串是用引号括起来的Unicode代码点序列 (U + 0022)。的字符除外,所有字符都可以放在引号内 必须转义的字符:引号(U+0022),倒装固体字符 (U+005C),控制字符U+0000 ~ U+001F。有两个字符 某些字符的转义序列表示。

所以不能直接传递0x0A或0x0C代码。这是禁止的!规范建议对从U+0000到U+001F的一些定义良好的代码使用转义序列:

\f表示换行字符(U+000C)。 \n表示换行字符(U+000A)。

因为大多数编程语言使用\来引用,你应该转义转义语法(双转义-一次用于语言/平台,一次用于JSON本身):

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

其他回答

我在PHP 4中创建一个类来模拟json_encode(在PHP 5中可用)时遇到了这个问题。下面是我想到的:

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

我遵循了这里提到的规则。我只使用了我需要的,但我认为您可以根据您所使用的语言对其进行调整以满足您的需要。在我的情况下,问题并不像我最初认为的那样是换行,而是关于/没有被转义。我希望这能防止别人像我一样头疼地发现我做错了什么。

我使用这个函数来剥离数据中的换行符或其他字符来解析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']);

这是你想要的:

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

您需要转义字符串中的\(将其转换为双\),否则它将成为JSON源中的换行符,而不是JSON数据。

TLDR:作者问题的解决方案。

您生成的json是错误的,因为它在其中一个值中包含换行符。要在其中一个值中生成一个表示(不包含)换行符的json,您可以使用:

使用字符串。原始的文字:

var data = String.raw`{"count" : 1, "stack" : "sometext\n\n"}`;

或应用JSON。Stringify为一个javascript对象(首先是类似json的)。

var data = JSON.stringify({"count" : 1, "stack" : "sometext\n\n"});

出于某种原因,这里所有的答案都集中在如何在JavaScript中解析JSON字符串表示,这可能会导致关于如何在实际JSON中表示换行符的困惑。后者不依赖于语言。

严格根据题目:

我如何处理JSON中的换行符?

让我们假设你在node中使用以下代码解析一个JSON文件(它可以是任何语言):


let obj = JSON.parse(fs.readFileSync('file.json'));
console.log(obj.mykey)

下面是file.json中每个可能内容的输出:

输入1:

{
  "mykey": "my multiline
   value"
}

输出1:

SyntaxError: Unexpected token

输入2:

{
  "mykey": "my multiline\nvalue"
}

输出2:

my multiline
value

输入3:

{
  "mykey": "my multiline\\nvalue"
}

3:输出

my multiline\nvalue

结论1:

要在json文件中表示换行符,我们应该使用\n字符。我们应该用\\n来表示\n。


我们如何使用JavaScript(而不是输入文件)定义上述每个输入:

当我们需要在JavaScript中定义一个包含JSON的字符串时,事情会发生一些变化,因为\n对于JavaScript也有特殊的意义。但还要注意String。原始文字修复了这个问题。

Input1:

let input1 = '{"mykey": "my multiline\nvalue"}'

//OR
let input1 = `{
  "mykey": "my multiline
   value"
}`;
//(or even)
let input1 = `{
  "mykey": "my multiline\nvalue"
}`;

//OR
let input1 = String.raw`{
  "mykey": "my multiline
   value"
}`;

console.log(JSON.parse(input1).mykey);

//SyntaxError: Unexpected token
//in JSON at position [..]

输入2:

let input2 = '{"mykey": "my multiline\\nvalue"}'

//OR
let input2 = `{
  "mykey": "my multiline\\nvalue"
}`;

//OR (Notice the difference from default literal)
let input2 = String.raw`{
  "mykey": "my multiline\nvalue"
}`;

console.log(JSON.parse(input2).mykey);

//my multiline
//value

输入3:

let input3 = '{"mykey": "my multiline\\\\nvalue"}'

//OR
let input3 = `{
  "mykey": "my multiline\\\\nvalue"
}`;

//OR (Notice the difference from default literal)
let input3 = String.raw`{
  "mykey": "my multiline\\nvalue"
}`;

console.log(JSON.parse(input3).mykey);

//my multiline\nvalue

结论2:

要在javascript中定义一个json字符串,最简单的方法是使用string。raw,因为它不需要任何转义(除了backtick,它像这个字符串一样转义。生'abc ${“’”}def”)。

当然,在javascript中创建json最简单的方法通常是将javascript对象转换为json(使用json .stringify)。


重要提示:

Don't get confused by how chrome/firefox devtools preview variables containing newlines (e.g. when you just write the variable name and press Enter). When previewing objects they always represent newlines of string values like \n. But, when previewing a string (e.g. dataObj.stack) firefox will show a newline as an empty line but chrome will still show it as \n. So, to be safe, you should always preview with console.log(dataObj.stack) to better understand what's actually contained inside the specific variable.

你可能想看看这个c#函数来转义字符串:

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