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


202

를 사용하여 서버에 요청하고 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을 통해 작은 따옴표를 올바르게 전달할 수있는 방법이 없습니까?

답변:


325

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도 마찬가지입니다.


4
업데이트 : : JSON을 파싱 할 때 JQuery는 매우 제한적입니다. 경고를 시도하면 ($ .parseJSON ( "[\"Ciao \\ '\ "]")); 저스틴이보고 한 내용 때문에 작동하지 않습니다
daitangio

2
" Java 용 JSON의 Crockford의 org.json 구현은 더 허용되며 작은 따옴표 문자를 허용합니다. "# 좋은 습관 : 견고성 원칙
Duncan Jones

1
@DuncanJones - 브라우저 중 어느 것도 JSON과 관련하여 그 원리를 따를 것없는 이유에 대한 통찰력을 제공 할 수 있습니다이 문서 : joelonsoftware.com/items/2008/03/17.html
저스틴 이디어

1
이 응답에 의해 지적 @JustinEthier로 stackoverflow.com/a/25491642/759452 의 JSON 사양 tools.ietf.org/html/rfc7159는 말한다 Any character may be escaped일부 구현은 작은 따옴표 탈출 할 수 있도록 왜,이 설명 할 수있다.
Adrien

1
@AdrienBe-흥미롭지 만 ... 4 자리 16 진수로 구성된 문자가 이스케이프 될 수 있다는 의미입니까? 위의 상태 다이어그램과 RFC 섹션 7의 설명에 따르면 작성된 작은 따옴표를 이스케이프 처리하는 \'것은 여전히 ​​허용되지 않습니다. 이 시점에서 RFC가 더 명확하다면 좋을 것입니다.
Justin Ethier

15

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

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


29
아니요. 그냥 작은 따옴표를 사용하십시오.
Jeff Kaufman

때로는 많은 수의 백 틱보다 유니 코드를 사용하는 것이 더 쉬운 경우가 있습니다. 특히 백틱이 번갈아 나타날 때.
slf

3
왜 백틱이 필요합니까? "foo 'bar'"와 같은 문자열이 있으면 작은 따옴표를 이스케이프 처리하지 않은 상태로 두십시오.
Jeff Kaufman

3
정확히 내가 찾던 것. 페이지에 json 문자열을 js 문자열 var로 작성하고 작은 따옴표로 묶으려고하는데 속성 값에 작은 따옴표가있을 때마다 일찍 종료되었습니다. 이제 페이지에 코드를 작성하기 전에 코드 뒤에 json.Replace ( " '", "\ u0027")를 수행합니다.
Zack

@Zack JSON을 따옴표로 묶지 않아야합니다. 기존 JSON 문자열에서 문자열이 필요한 경우 다시 문자열 화하십시오. PHP에서, 그것은 이전의 결과 가 될 것입니다 var jsonEncodedAsString = <?= json_encode(myEncodedJson) ?>. 작은 따옴표를 이스케이프 처리 할 것입니다. 실제로 큰 따옴표로 묶인 큰 문자열을 출력하므로 작은 따옴표는 이스케이프되지 않지만 큰 따옴표는 의지. myEncodedJsonjson_encode
Juan Mendes

5

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

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

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

감사


'<? = $ marker; ?> '이것은 유효한 json이 아닙니다. 주변 인용 부호는 자바 스크립트 인터프리터에 의해 "먹히고", <...로 시작하는 문자열은 다음 중 하나입니다 : jQuery.parseJSON ( ' "<? = $ marker;?>" '); jQuery.parseJSON ( "\"<? = $ marker;?> \ ""); 사양에 따르면 json 문자열은 큰 따옴표를 사용해야하지만 자바 스크립트는 신경 쓰지 않으므로 작은 따옴표 자바 스크립트 문자열이나 큰 따옴표가 있지만 후자를 사용하면 모든 문자열을 이스케이프 처리해야합니다. 문자열 안에 큰 따옴표를 사용합니다.
Chris Cogdon

3

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

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

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

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

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


1
그러나 JSON 문자열의 일부로 전달할 때 작은 따옴표를 이스케이프 처리 할 필요는 없습니다.
Justin Ethier

2

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

1

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.

0

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

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


PHP에서 라이브러리를 사용하여 JSON 객체를 생성합니다. 지적 해 주셔서 감사합니다.
Erik Čerpnjak
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.