[javascript] JSON에서 이스케이프 된 작은 따옴표로 인해 jQuery.parseJSON에서 “잘못된 JSON”오류가 발생 함

를 사용하여 서버에 요청하고 jQuery.post()있으며 서버가 (예 🙂 JSON 객체를 반환하고 { "var": "value", ... }있습니다. 그러나 값 중 하나에 작은 따옴표가 올바르게 포함되어 있으면 (예 : 이스케이프 처리 \') jQuery가 유효한 JSON 문자열을 구문 분석하지 못합니다. 다음 은 Chrome 콘솔에서 수행 한 의미의 예입니다 .

data = "{ \"status\": \"success\", \"newHtml\": \"Hello \\\'x\" }";
eval("x = " + data); // { newHtml: "Hello 'x", status: "success" }

$.parseJSON(data); // Invalid JSON: { "status": "success", "newHtml": "Hello \'x" }

이것이 정상입니까? JSON을 통해 작은 따옴표를 올바르게 전달할 수있는 방법이 없습니까?



답변

JSON 웹 사이트 의 상태 머신 다이어그램에 따르면 이스케이프 된 큰 따옴표 문자 만 사용할 수 있고 작은 따옴표는 사용할 수 없습니다. 작은 따옴표는 이스케이프 할 필요가 없습니다.

http://www.json.org/string.gif

업데이트 -관심있는 사람들을위한 추가 정보 :


Douglas Crockford는 JSON 사양이 문자열 내에서 이스케이프 된 작은 따옴표를 허용하지 않는 이유를 구체적으로 말하지 않습니다. 그러나 JavaScript의 부록 E : The Good Parts 에서 JSON에 대해 논의하는 동안 그는 다음과 같이 씁니다.

JSON의 디자인 목표는 최소한의 이식성, 텍스트 및 JavaScript의 하위 집합이었습니다. 상호 운용하기 위해 동의 할 필요가 적을수록 더 쉽게 상호 운용 할 수 있습니다.

따라서 그는 모든 JSON 구현에서 동의 해야하는 규칙 중 하나이기 때문에 큰 따옴표를 사용하여 문자열 만 정의하도록 결정했을 것입니다. 결과적으로 문자열은 큰 따옴표 문자로만 종료 할 수 있기 때문에 문자열 내의 작은 따옴표 문자가 실수로 문자열을 종료하는 것은 불가능합니다. 따라서 공식 사양에서 작은 따옴표 문자를 이스케이프 처리 할 필요가 없습니다.


조금 더 깊이 파고, 크록 포드의 org.json의 Java 용 JSON의 구현은 더 허용하고 않는 작은 따옴표 문자를 사용할 수 :

toString 메소드로 생성 된 텍스트는 JSON 구문 규칙을 엄격하게 준수합니다. 생성자는 그들이 받아 들일 텍스트에서 더 관대합니다.

  • 문자열은 ‘(작은 따옴표)로 인용 될 수 있습니다.

이것은 JSONTokener 소스 코드에 의해 확인됩니다 . 이 nextString방법은 이스케이프 된 작은 따옴표 문자를 허용하고 큰 따옴표 문자처럼 취급합니다.

public String nextString(char quote) throws JSONException {
    char c;
    StringBuffer sb = new StringBuffer();
    for (;;) {
        c = next();
        switch (c) {

        ...

        case '\\':
            c = this.next();
            switch (c) {

            ...

            case '"':
            case '\'':
            case '\\':
            case '/':
                sb.append(c);
                break;
        ...

이 방법의 맨 위에는 유익한 주석이 있습니다.

공식 JSON 형식은 작은 따옴표로 문자열을 허용하지 않지만 구현에서는 문자열을 허용 할 수 있습니다.

따라서 일부 구현은 작은 따옴표를 허용하지만 이것에 의존해서는 안됩니다. 많은 대중적인 구현은 이와 관련하여 상당히 제한적이며 작은 따옴표로 묶인 문자열 및 / 또는 이스케이프 된 작은 따옴표를 포함하는 JSON을 거부합니다.


마지막으로 이것을 원래 질문에 다시 연결하기 위해 jQuery.parseJSON 하기 위해 먼저 브라우저의 기본 JSON 파서 또는 json2.js 와 같은로드 된 라이브러리를 사용하려고 시도합니다 (측면에서 jQuery 논리가 JSON정의되지 않은 경우 라이브러리입니다 ) . 따라서 jQuery는 기본 구현만큼이나 관용적 일 수 있습니다.

parseJSON: function( data ) {
    ...

    // Attempt to parse using the native JSON parser first
    if ( window.JSON && window.JSON.parse ) {
        return window.JSON.parse( data );
    }

    ...

    jQuery.error( "Invalid JSON: " + data );
},

내가 아는 한이 구현은 공식 JSON 사양 만 준수하고 작은 따옴표를 허용하지 않으므로 jQuery도 마찬가지입니다.


답변

문자열 안에 작은 따옴표가 필요한 경우 사양에 의해 \ ‘가 정의되어 있지 않으므로 http://www.utf8-chartable.de/\u0027 참조하십시오 .

편집 : 의견에 백틱 단어를 오용하는 것을 용서하십시오. 나는 백 슬래시를 의미했다. 여기서 요점은 다른 문자열 안에 문자열을 중첩 한 경우 많은 백 슬래시 대신 유니 코드를 사용하여 작은 따옴표를 피하는 것이 더 유용하고 읽기 쉽다는 것입니다. 그러나 중첩되어 있지 않으면 거기에 평범한 오래된 인용문을 넣는 것이 더 쉽습니다.


답변

문제가 어디에 있는지, 사양을 볼 때 이스케이프 처리되지 않은 작은 따옴표가 올바르게 구문 분석되어야한다는 것이 분명합니다.

jquery의 jQuery.parseJSON 함수를 사용하여 JSON 문자열을 구문 분석하지만 json_encode로 준비된 데이터에 작은 따옴표가 있으면 구문 분석 오류가 발생합니다.

내 구현에서 다음과 같은 실수 일 수 있습니까 (PHP-서버 측).

$data = array();

$elem = array();
$elem['name'] = 'Erik';
$elem['position'] = 'PHP Programmer';
$data[] = json_encode($elem);

$elem = array();
$elem['name'] = 'Carl';
$elem['position'] = 'C Programmer';
$data[] = json_encode($elem);

$jsonString = "[" . implode(", ", $data) . "]";

마지막 단계는 JSON 인코딩 문자열을 JS 변수에 저장하는 것입니다.

<script type="text/javascript">
employees = jQuery.parseJSON('<?=$marker; ?>');
</script>

”대신 “”를 사용하면 여전히 오류가 발생합니다.

해결책:

나를 위해 일한 유일한 방법은 비트 마스크 JSON_HEX_APOS를 사용하여 작은 따옴표를 다음과 같이 변환하는 것입니다.

json_encode($tmp, JSON_HEX_APOS);

이 문제를 해결하는 다른 방법이 있습니까? 내 코드가 잘못되었거나 잘못 작성 되었습니까?

감사


답변

쿼리에서 작은 따옴표를 보낼 때

empid = " T'via"
empid =escape(empid)

작은 따옴표를 포함하여 값을 얻는 경우

var xxx  = request.QueryString("empid")
xxx= unscape(xxx)

검색어에 작은 따옴표가 포함 된 값을 검색 / 삽입하려는 경우
xxx=Replace(empid,"'","''")


답변

PHP의 native를 사용하여 JavaScript 스크립트 블록을 출력하기 위해 CakePHP를 사용하여 비슷한 문제를 발견했습니다 json_encode. $contractorCompanies작은 따옴표가 있고 위에 설명 된대로 json_encode($contractorCompanies)유효한 값이 포함되어 있으며 유효한 JSON으로 인해 이스케이프되지 않습니다.

<?php $this->Html->scriptBlock("var contractorCompanies = jQuery.parseJSON( '".(json_encode($contractorCompanies)."' );"); ?>

JSON 인코딩 문자열 주위에 addslashes ()를 추가하면 Cake / PHP가 올바른 자바 스크립트를 브라우저에 반영 할 수 있도록 따옴표를 이스케이프 처리합니다. JS 오류가 사라집니다.

<?php $this->Html->scriptBlock("var contractorCompanies = jQuery.parseJSON( '".addslashes(json_encode($contractorCompanies))."' );"); ?>


답변

XHR 요청의 JSON 객체를 HTML5 data- * 속성으로 저장하려고했습니다. 나는 위의 많은 솔루션을 성공하지 않고 시도했습니다.

내가 마지막으로 끝내는 것은 stringify () 메서드 호출 후 다음과 같은 방법으로 작은 따옴표 '&#39;정규 표현식을 사용하는 코드 로 바꾸는 것입니다.

var productToString = JSON.stringify(productObject);
var quoteReplaced = productToString.replace(/'/g, "&#39;");
var anchor = '<a data-product=\'' + quoteReplaced + '\' href=\'#\'>' + productObject.name + '</a>';
// Here you can use the "anchor" variable to update your DOM element.


답변

흥미 롭군 서버 쪽에서 JSON을 어떻게 생성합니까? 라이브러리 기능을 사용하고 있습니까 (예 :json_encode PHP) , 아니면 JSON 문자열을 직접 작성하고 있습니까?

내 관심을 끄는 유일한 것은 탈출 아포스트로피 ( \')입니다. 큰 따옴표를 사용하면서 실제로 따옴표를 이스케이프 할 필요가 없습니다. 아직 버전 1.4.1로 업데이트하지 않았으므로 실제로 jQuery 오류의 원인인지 확인할 수 없습니다.