JSON'daki yeni satırları nasıl ele alırım?


289

Bazı JSON oluşturdum ve JavaScript'te bir nesneye çekmeye çalışıyorum. Hata almaya devam ediyorum. İşte sahip olduğum şeyler:

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

Bu bana bir hata veriyor:

unterminated string literal

İle JSON.parse(data)benzer hata mesajlarını görüyorum: Unexpected token ↵Chrome'da " unterminated string literal" ve Firefox ve IE'de " ".

Ben her iki durumda \nsonra sometexthata giderir zaman ortadan kalkar. Neden \nmarka evalve JSON.parsebaşarısız olduğunu anlayamıyorum .


19
Eval yerine gerçek bir json ayrıştırıcı kullanmayı deneyin.
Eric

Yanıtlar:


368

Sanırım istediğin bu:

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

(Dizenizdeki "\" karakterinden kaçmanız gerekir (bunu bir "-" çiftine dönüştürür), aksi takdirde JSON verilerinde değil JSON kaynağında yeni bir satır olur.)


101
Bu elbette doğrudur, ancak bunu yapmak için bir neden eklemek istiyorum: ietf.org/rfc/rfc4627.txt adresindeki JSON özelliği , bu cümleyi bölüm 2.5'te içeriyor: "Tüm Unicode karakterleri kaçması gereken karakterler hariç tırnak işaretleri: tırnak işareti, ters katı ve kontrol karakterleri (U + 0000 - U + 001F). " Yeni satır bir kontrol karakteri olduğundan, bu karakterden kaçılmalıdır.
daniel kullmann

1
Www.json.org'a göre JSON, dizelerde "\ n" kontrol sırasını kabul eder - ve JSON.parse (['"a \\ na"']) [1] .charCodeAt (); son 10 kez "Linefeed" olan 10 gösterecektir. --- BTW: Çığlık atmayı kes!
BlaM

+ 1. JSON kodlamasını anlama konusunda sorun yaşıyordum ama "JSON verilerinde değil JSON kaynağında yeni bir satır olacak" benim için açıklığa kavuştu.
amucunguzi

44

Sen yerini alan bir fonksiyon olması gerekir \niçin \\nbu durumda databir dize değil.

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

Sonuç dataObjolacaktır

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

3
Eğer kaçış karakterleri kaçmak gerekir (yani .replace("\\n", "\\\\n")) ve ben de birden fazla örnek (yani .replace(/\n/g, "\\\\n")) yerine izin vermek için regex kullanmanızı öneririz
musefan

2
neden kaçış karakterlerinden kaçmalısın? Yani .replace("\n", "\\n")işi iyi yapmak gibi bir şey demek !! Örneğin var test = [{"description":"Some description about the product. This can be multi-line text."}]; console.log(JSON.parse(test.replace(/\n/g, "\\n")));, nesneyi tarayıcı konsoluna mükemmel şekilde [{"description":"Some description about the product.\nThis can be multi-line text."}]
gönderir

BTW, yukarıdaki yorumda, orijinal JSON dizesi stackoverflow'un yorum biçimlendiricisi tarafından kaldırılan yeni bir satıra sahiptir. Değiştirmeden sonraki son çıktının \ndeğere yeni bir satır karakteri eklemesi gerektiğini görebilirsiniz .
Fr0zenFyr

1
-1 Bu yanıt önce geçersiz bir JSON dizesi oluşturur (yeni satır bir denetim karakteri olduğundan), daha sonra bir dizi eksik değiştirmeyle düzeltmeye çalışır (3'ten fazla denetim karakteri vardır). Daha sonra, üst üste, evalişlevi kullanmayı başarır . 17 upvotes ???
Phil

1
Kaçması gereken tırnak işaretleri ne olacak?
tek başına

8

Spesifikasyona göre, http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf :

Dize, tırnak işaretleri ( U+0022) ile sarılmış Unicode kod noktalarının bir dizisidir . Bütün karakterler şekilde çıkmalıdır karakterleri dışındaki tırnak içine yerleştirilebilir: tırnak işareti ( U+0022), ters solidus'un ( U+005C) ve kontrol karakterleri U+0000için U+001F. Bazı karakterlerin iki karakterli kaçış dizisi gösterimleri vardır.

Böylece doğrudan geçemez 0x0Aveya 0x0Ckod yazamazsınız. Yasaktır! Özellikleri bazı iyi tanımlanmış kodlar için çıkış-sekanslarının kullanımı da anlaşılacağı U+0000üzere U+001F:

  • \fform besleme karakterini ( U+000C) temsil eder .
  • \nsatır besleme karakterini ( U+000A) temsil eder .

Programlama dillerinin çoğu \alıntı için kullandığından , kaçış sözdiziminden (çift kaçış - bir kez dil / platform için, bir kez JSON'un kendisi için) kaçmalısınız:

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

3

Örneğin, JSON alanının değerini yazarken dizenizdeki dizeden kaçabilir ve örneğin istemci tarayıcısında değeri alırken dizgisini kaldırabilirsiniz.

Tüm büyük tarayıcıların JavaScript uygulaması unescape komutuna sahiptir.

Misal:

Sunucuda:

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

Tarayıcıda:

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

2

Dizeden kaçmak için bu C # işlevine bakmak isteyebilirsiniz:

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
Bu neden kaçıyor >?
hiçbir şey

0

JSON verileri ayrıştırmak için veri satırsonu veya diğer karakterleri şerit için bu işlevi kullandım:

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
Çoğu dilde, kendi eşleme işlevinizi yazmaktan çok unicode dizelerden aksanları çıkarmanın daha iyi yolları vardır.
Python'da

ya da farklı dillerde özel karakterleri kontrol etmenin birçok yolu var.
ShivarajRH

2
Onları genel olarak soymak çok kötü. Onları XML sayısal karakter referansı olarak daha iyi kodlayın ve ardından alıcı uçta kod çözme.
Annarfych

0

JSON.stringify

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

yukarıdaki dizeyi

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

burada belirtildiği gibi

json dizgi

Bu işlev, giriş dizesinin başına ve sonuna çift tırnak ekler ve özel JSON karakterlerinden kaçar. Özellikle, yeni satır \ n karakteriyle değiştirilir, sekme \ t karakteriyle değiştirilir, ters eğik çizgi iki ters eğik çizgi ile değiştirilir \ ve her tırnak işaretinin önüne bir ters eğik çizgi yerleştirilir.


4
Bu, sadece mevcut sekiz cevaplı on bir yaşındaki bir sorunun kodudur. Kodu açıklamak ve ayrıca cevabınızın hangi yeni yönünü ele aldığını ve zamanın geçişinin ve yeni sürümlerin yayınlanmasının cevabınızı etkileyip etkilemediğini açıklamak yararlı olacaktır.
Jason Aller

-1

Ben PHP 4 json_encode taklit etmek için bir sınıf yaparken bu sorunla karşılaştı (PHP 5 mevcuttur). İşte ben geldim:

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

Burada belirtilen kurallara uydum . Sadece ihtiyacım olanı kullandım, ama kullandığınız dilde ihtiyaçlarınıza göre uyarlayabileceğinizi düşünüyorum. Benim durumumdaki problem, başlangıçta düşündüğüm gibi yeni satırlarla ilgili değil, kaçmak / kaçmamakla ilgiliydi. Umarım bu, başka birinin neyi yanlış yaptığımı anlamaya çalıştığım küçük baş ağrısından korur.


2
Json.org'da belirtilen 6 kontrol karakteri kısayolu, tüm kontrol karakterlerinin kapsamlı bir listesi değildir. Sonuç olarak, bu işlev geçersiz JSON oluşturabilir.
Phil

-5

Sana bir soru anlıyorum gibi, size kod içine JSON kopyalayıp yapıştırın çünkü doğrudan JSON ayrıştırma ilgili değil - bu daha sonra sadece JSON doğrudan kopyalama durumda eğer öyleyse dataObjtek tırnak ile sarmadan değişken (ipucu: eval==evil)

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

console.log(dataObj);

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.