Làm cách nào để xử lý các dòng mới trong JSON?


289

Tôi đã tạo một số JSON và tôi đang cố gắng kéo nó vào một đối tượng trong JavaScript. Tôi cứ bị lỗi. Đây là những gì tôi có:

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

Điều này cho tôi một lỗi:

unterminated string literal

Với JSON.parse(data), tôi thấy các thông báo lỗi tương tự: " Unexpected token ↵" trong Chrome và " unterminated string literal" trong Firefox và IE.

Khi tôi đưa ra \nsau khi sometextlỗi đi trong cả hai trường hợp. Tôi dường như không thể tìm ra lý do tại sao \nlàm evalJSON.parsethất bại.


19
Hãy thử sử dụng một trình phân tích cú pháp json thực sự thay vì eval.
Eric

Câu trả lời:


368

Tôi đoán đây là những gì bạn muốn:

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

(Bạn cần thoát "\" trong chuỗi của mình (biến nó thành một chuỗi - "\"), nếu không, nó sẽ trở thành một dòng mới trong nguồn JSON, không phải dữ liệu JSON.)


101
Điều này tất nhiên là đúng, nhưng tôi muốn thêm lý do phải làm điều này: thông số JSON tại ietf.org/rfc/rfc4627.txt chứa câu này trong phần 2.5: "Tất cả các ký tự Unicode có thể được đặt trong dấu ngoặc kép ngoại trừ các ký tự phải được thoát: dấu ngoặc kép, solidus ngược và ký tự điều khiển (U + 0000 đến U + 001F). " Vì một dòng mới là một nhân vật điều khiển, nó phải được thoát.
daniel kullmann

1
Theo www.json.org JSON không chấp nhận chuỗi điều khiển "\ n" trong chuỗi - và nếu bạn thử JSON.parse (['"a \\ na"']) [1] .charCodeAt (); nó sẽ hiển thị 10 - đó là "Linefeed" lần cuối cùng tôi kiểm tra. --- BTW: Đừng la hét!
BlaM

+ 1. Tôi gặp khó khăn khi hiểu mã hóa JSON nhưng "sẽ trở thành một dòng mới trong nguồn JSON, không phải dữ liệu JSON" cho tôi thấy rõ.
amucunguzi

44

Bạn sẽ cần phải có một chức năng thay thế \nđể \\ntrong trường hợp datakhông phải là một chuỗi chữ.

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

Kết quả dataObjsẽ là

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

3
bạn cần phải thoát các ký tự thoát của mình (tức là .replace("\\n", "\\\\n")) và tôi cũng sẽ đề nghị sử dụng regex để cho phép thay thế nhiều trường hợp (ví dụ .replace(/\n/g, "\\\\n"))
musefan

2
Tại sao bạn cần phải thoát khỏi nhân vật thoát? Tôi có nghĩa là một cái gì đó như .replace("\n", "\\n")nên làm công việc tốt !! Ví dụ: var test = [{"description":"Some description about the product. This can be multi-line text."}]; console.log(JSON.parse(test.replace(/\n/g, "\\n")));sẽ xuất đối tượng hoàn toàn tốt cho bảng điều khiển trình duyệt dưới dạng[{"description":"Some description about the product.\nThis can be multi-line text."}]
Fr0zenFyr

BTW, trong nhận xét trên, chuỗi JSON gốc có một dòng mới, được loại bỏ bởi bộ định dạng nhận xét của stackoverflow .. Bạn có thể thấy rằng đầu ra cuối cùng sau khi thay thế sẽ chèn một char dòng mới \nvào giá trị.
Fr0zenFyr

1
-1 Câu trả lời này trước tiên xây dựng một chuỗi JSON không hợp lệ (vì dòng mới là ký tự điều khiển), sau đó cố gắng sửa nó bằng một loạt các thay thế không hoàn chỉnh (có nhiều hơn 3 ký tự điều khiển). Sau đó, để đầu nó ra, nó cũng quản lý để sử dụng evalchức năng. 17 upvote ???
Phil

1
Điều gì về dấu ngoặc kép cần phải được thoát quá?
độc lập

8

Theo thông số kỹ thuật, http : //www.ecma-i Intl.org/publications/files/ECMA-ST/ECMA-404.pdf :

Chuỗi là một chuỗi các điểm mã Unicode được bao bọc bằng dấu ngoặc kép ( U+0022). Tất cả các ký tự có thể được đặt trong dấu ngoặc kép trừ các ký tự phải được thoát: dấu ngoặc kép ( U+0022), solidus ( U+005C) và ký tự điều khiển U+0000tới U+001F. Có đại diện trình tự thoát hai ký tự của một số nhân vật.

Vì vậy, bạn không thể vượt qua 0x0Ahoặc 0x0Cmã trực tiếp. Nó bị cấm! Thông số kỹ thuật gợi ý sử dụng các chuỗi thoát cho một số mã được xác định rõ từ U+0000đến U+001F:

  • \fđại diện cho ký tự nguồn cấp dữ liệu ( U+000C).
  • \nđại diện cho ký tự nguồn cấp dữ liệu ( U+000A).

Vì hầu hết các ngôn ngữ lập trình sử dụng \để trích dẫn, bạn nên thoát cú pháp thoát (thoát kép - một lần cho ngôn ngữ / nền tảng, một lần cho chính JSON):

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

3

Bạn chỉ có thể thoát chuỗi của mình trên máy chủ khi viết giá trị của trường JSON và bỏ hiển thị chuỗi đó khi truy xuất giá trị trong trình duyệt máy khách.

Việc triển khai JavaScript của tất cả các trình duyệt chính có lệnh unescape.

Thí dụ:

Trên máy chủ:

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

Trong trình duyệt:

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

2

Bạn có thể muốn xem xét hàm C # này để thoát chuỗi:

http://www.aspcode.net/C-encode-a-opes-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
Tại sao điều này thoát >?
gì cần thiết

0

Tôi đã sử dụng chức năng này để loại bỏ dòng mới hoặc các ký tự khác trong dữ liệu để phân tích dữ liệu 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
Trong hầu hết các ngôn ngữ, bạn có những cách tốt hơn để loại bỏ các dấu từ các chuỗi unicode hơn là viết ra chức năng ánh xạ của riêng bạn. Xem câu hỏi này để biết ví dụ về python: stackoverflow.com/questions/517923/
triệt

ya chúng ta có nhiều cách để kiểm soát các ký tự đặc biệt trong các ngôn ngữ khác.
ShivarajRH

2
Đó là tất cả các loại xấu để loại bỏ chúng nói chung. Tốt hơn mã hóa chúng dưới dạng tham chiếu ký tự số XML và sau đó giải mã khi kết thúc nhận.
Annarfych

0

JSON.opesify

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

sẽ chuyển đổi chuỗi trên thành

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

như đã đề cập ở đây

json xâu chuỗi

Hàm này thêm dấu ngoặc kép ở đầu và cuối chuỗi đầu vào và thoát các ký tự JSON đặc biệt. Cụ thể, một dòng mới được thay thế bằng ký tự \ n, một tab được thay thế bằng ký tự \ t, dấu gạch chéo ngược được thay thế bằng hai dấu gạch chéo ngược \ và dấu gạch chéo ngược được đặt trước mỗi dấu ngoặc kép.


4
Đây là một mã chỉ trả lời cho một câu hỏi mười một tuổi với tám câu trả lời hiện có khác. Rất hữu ích để giải thích mã, và cũng để giải thích khía cạnh mới của câu hỏi mà câu trả lời của bạn giải quyết, và nếu thời gian và việc phát hành phiên bản mới tác động đến câu trả lời của bạn.
Jason Aller

-1

Tôi đã gặp vấn đề đó trong khi tạo một lớp trong PHP 4 để mô phỏng json_encode (có sẵn trong PHP 5). Đây là những gì tôi nghĩ ra:

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

Tôi đã làm theo các quy tắc được đề cập ở đây . Tôi chỉ sử dụng những gì tôi cần, nhưng tôi cho rằng bạn có thể điều chỉnh nó theo nhu cầu của bạn bằng ngôn ngữ bạn đang sử dụng. Vấn đề trong trường hợp của tôi không phải là về các dòng mới như tôi nghĩ ban đầu, mà là về việc / không được thoát. Tôi hy vọng điều này ngăn người khác khỏi cơn đau đầu nhỏ mà tôi đã tìm ra những gì tôi đã làm sai.


2
6 tốc ký cho các ký tự điều khiển được chỉ định trên json.org không phải là danh sách đầy đủ tất cả các ký tự điều khiển. Kết quả là, hàm này có thể tạo JSON không hợp lệ.
Phil

-5

Theo tôi hiểu câu hỏi của bạn, đó không phải là phân tích cú pháp JSON vì bạn có thể sao chép-dán JSON trực tiếp vào mã của mình - vì vậy nếu đây là trường hợp thì chỉ cần sao chép trực tiếp JSON của bạn sang dataObjbiến mà không gói nó bằng dấu ngoặc đơn (mẹo eval==evil:)

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

console.log(dataObj);

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.