如何处理JSON中的换行符?


288

我生成了一些JSON,并尝试将其拉入JavaScript中的对象。我不断出错。这是我所拥有的:

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

这给我一个错误:

unterminated string literal

使用JSON.parse(data),我会看到类似的错误消息:Unexpected token ↵Chrome中的“ unterminated string literal” ,以及Firefox和IE中的“ ”。

当我取出\nsometext,两种情况下错误都会消失。我似乎无法找出原因的\n品牌evalJSON.parse失败。


19
尝试使用真正的json解析器而不是eval。
艾瑞克(Eric)

Answers:


367

我想这就是你想要的:

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

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


100
这当然是正确的,但是我想补充一下这样做的原因:ietf.org/rfc/rfc4627.txt上的JSON规范在第2.5节中包含以下语句:“所有Unicode字符都可以放在引号,但必须转义的字符除外:引号,反斜线和控制字符(U + 0000至U + 001F)。” 由于换行符是控制字符,因此必须对其进行转义。
丹尼尔·库尔曼

1
根据www.json.org的说法,JSON确实接受字符串中的控制序列“ \ n”-如果尝试使用JSON.parse(['“ a \\ na”'])[1] .charCodeAt(); 将会显示10-这是我上次检查时的“换行”。--- BTW:别再尖叫了!
BlaM 2015年

+ 1.我在理解JSON编码时遇到了麻烦,但是“这将成为JSON源中的换行符,而不是JSON数据”对我来说很清楚。
amucunguzi

44

你需要有它取代的功能\n\\n的情况下,data是不是一个字符串。

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

结果dataObj将是

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

3
您需要转义转义字符(即.replace("\\n", "\\\\n")),我也建议使用正则表达式以允许替换多个实例(即.replace(/\n/g, "\\\\n")
musefan 2012年

2
为什么需要逃脱转义字符?我的意思是说.replace("\n", "\\n")应该做得很好!例如,var test = [{"description":"Some description about the product. This can be multi-line text."}]; console.log(JSON.parse(test.replace(/\n/g, "\\n")));将对象完美地输出到浏览器控制台为[{"description":"Some description about the product.\nThis can be multi-line text."}]
Fr0zenFyr 2015年

顺便说一句,在上面的注释中,原始JSON字符串有一个新行,由stackoverflow的注释格式化程序删除\n
Fr0zenFyr

1
-1此答案首先构造一个无效的JSON字符串(因为换行符是控制字符),然后尝试使用一系列不完整的替换(有3个以上的控制字符)来修复它。然后最重要的是,它还设法使用了该eval功能。17赞
菲尔(Phil)

1
那么也需要转义的引号呢?
单独站立

8

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

字符串是用引号(U+0022)括起来的Unicode代码点的序列。所有字符可放置在引号内除了必须转义字符:引号(U+0022),固相线反向(U+005C),并控制字符U+0000U+001F。有些字符有两个字符的转义序列表示。

因此,您不能直接通过0x0A0x0C编码。这是被禁止的!该规范建议将转义序列用于一些明确定义的代码,从U+0000U+001F

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

正如大多数编程语言\用于引用一样,您应转义转义语法(双转义-一次用于语言/平台,一次用于JSON本身):

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

3

例如,您可以在写入JSON字段的值时在服务器上转义字符串,而在客户端浏览器中获取值时取消转义字符串。

所有主要浏览器的JavaScript实现都具有unescape命令。

例:

在服务器上:

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

在浏览器中:

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

2

您可能需要研究以下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(); 
} 

3
为什么会逃脱>
没必要,2015年

0

我使用此函数来去除数据中的换行符或其他字符以解析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',
        "`" => "'", "´" => "'",  '"' => ',',  '`' => "'",
        '´' => "'", '"' => '\"', '"' => "\"", '´' => "'",
        "&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']);

9
在大多数语言中,与写下自己的映射功能相比,从unicode字符串中去除重音是更好的方法。看到这个问题在Python中的例子:stackoverflow.com/questions/517923/...
MiniQuark

是的,我们有很多方法可以控制差异语言中的特殊字符。
ShivarajRH

2
一般来讲,剥离它们真是不好。更好地将它们编码为XML数字字符引用,然后在接收端进行解码。
Annarfych '16

0

JSON.stringify

JSON.stringify(`{ 
  a:"a"
}`)

将上述字符串转换为

"{ \n      a:\"a\"\n    }"

如这里提到的

json串化

此函数在输入字符串的开头和结尾添加双引号,并转义特殊的JSON字符。特别是,用\ n字符替换换行符,用\ t字符替换制表符,用两个反斜杠\替换反斜杠,并在每个引号之前放置一个反斜杠。


4
这是仅一个十一岁问题的代码答案,另外八个已有答案。解释代码,解释答案所涉及的问题的新方面,以及时间的流逝和新版本的发布是否会影响您的答案,这将非常有用。
杰森·艾勒

-1

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

我遵循这里提到的规则。我只使用了我需要的内容,但是我认为您可以使用所使用的语言来使其适应您的需求。在我的情况下,问题不是我最初想到的换行符,而是/不被忽略。我希望这可以防止其他人因我弄清楚自己做错了什么而感到头疼。


2
json.org上指定的6个控制字符速记不是所有控制字符的详尽列表。结果,此函数可能生成无效的JSON。
菲尔(Phil)

-5

据我了解你的问题,它不是关于解析JSON,因为您可以将您的JSON复制粘贴到你的代码中直接-所以,如果是这样的话那么就复制你的JSON直接到dataObj变量,而不单引号包裹它(提示:eval==evil

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

console.log(dataObj);

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.