jQuery는 AJAX 쿼리에서 내 JSON을 구문 분석하지 않습니다.


88

jQuery.ajax ()를 사용하여 서버에서 반환 된 일부 JSON 데이터를 구문 분석하는 데 어려움이 있습니다.

AJAX를 수행하려면 다음을 사용합니다.

$.ajax({
  url: myUrl,
  cache: false,
  dataType: "json",
  success: function(data){
    ...
  },
  error: function(e, xhr){
    ...
  }
});  

그리고 항목 배열을 반환하면 제대로 작동합니다.

[ { title: "One", key: "1" }, { title: "Two", key: "2" } ]

성공 함수가 호출되고 올바른 개체를받습니다.

그러나 단일 객체를 반환하려고 할 때 :

{ title: "One", key: "1" } 

오류 함수가 호출되고 xhr에 'parsererror'가 포함됩니다. JSON을 전송하기 전에 서버에서 괄호로 묶어 보았지만 아무런 차이가 없습니다. 그러나 내용을 Javascript의 문자열에 붙여 넣은 다음 eval () 함수를 사용하면 완벽하게 평가됩니다.

내가 뭘 잘못하고 있는지 아이디어가 있습니까?

안토니


답변:


72

서버가 데이터를 Content-Type으로 보내고 "*/json"있습니까? 그렇지 않은 경우 응답 헤더를 적절히 수정하십시오. "application/json"예를 들어 전송 은 괜찮습니다.


둘째,이 추측은 한 번 같은 문제가 있었고 놀랍게도 잘못된 MIME 유형을 사용하고 있다는 것을 알게되었습니다. Windows에서 localhost를 통해 테스트하는 경우이를 잘 알고 있어야합니다. 어딘가에 업로드하고 다시 테스트 해보세요. localhost에서 작동하기를 원한다면 요청을 정말로 퍼지해야합니다.
Josh

51

json.org 사양 에 따르면 반품이 유효하지 않습니다. 이름은 항상 따옴표로 묶여 있으므로 반환해야합니다.

{ "title": "One", "key": "1" }

[ { "title": "One", "key": "1" }, { "title": "Two", "key": "2" } ]

이 중 하나가 지금 작동한다고 말했기 때문에 설정 문제가 아닐 수 있지만 나중에 다른 JSON 파서로 전환해야하는 경우를 대비하여 수정해야합니다.


2
실제로 jQuery 1.4 (예 { key: 'val' }:)에서는 유효한 JSON이 아닙니다.
rfunduk

34

JSON 문자열은 따옴표로 묶여 있습니다. 작은 따옴표는 유효한 대체물이 아닙니다.

{"who": "Hello World"}

유효하지만 이것은 아닙니다 ...

{'who': 'Hello World'}

OP의 문제는 아니지만 여기에 착륙하는 다른 사람들에게는 주목할 가치가 있다고 생각했습니다.


30

이 문제는 일반적으로 요청이 잘못된 MIME 유형을 수신했기 때문에 발생합니다. 자신의 컴퓨터에서 개발할 때 자신의 컴퓨터 인 "서버"에서 적절한 MIME 유형을받지 못하는 경우가 있습니다. 브라우저에서 로컬로 저장된 파일을 열어 개발할 때이 문제가 한 번 발생했습니다 (예 : URL은 "c : /project/test.html").

beforeSend 속성을 사용하여 MIME 유형을 재정의하는 콜백 함수를 추가해보십시오. 이것은 잘못된 MIME 유형이 서버에서 전송되고 호출 코드에서 수신 되었음에도 불구하고 코드가 json을 처리하도록 속일 것입니다. 다음은 몇 가지 예제 코드입니다.

이 질문 에 따르면 적절한 MIME 유형은 application / json 이지만 시도했을 때 application / j-son이 작동했다는 것을 알고 있습니다 (현재 몇 년 전). 아마도 application / json을 먼저 시도해야합니다.

var jsonMimeType = "application/json;charset=UTF-8";
$.ajax({
 type: "GET",
 url: myURL,
 beforeSend: function(x) {
  if(x && x.overrideMimeType) {
   x.overrideMimeType(jsonMimeType);
  }
 },
 dataType: "json",
 success: function(data){
  // do stuff...
 }
});

당신이 제안한 beforeSend 제안이 나를 위해 일했다고 말하고 싶습니다! 내 ajax 호출은 사파리와 크롬에서 훌륭하게 작동했지만 파이어 폭스는 아닙니다. beforeSend를 추가하자마자 Firefox가 시작되었습니다. 와!! 감사!!
Karmen Blake

7

나는이 문제가 있었고 조금 사용했습니다.

eval('('+data+')')

객체에서 반환 된 데이터를 가져옵니다. 그러나 나중에 괄호 안에 '누락)'오류가 발생하는 다른 문제가 발생했으며 jQuery에 json 구조에 대한 문자열을 평가하기위한 함수가 있음을 발견했습니다.

$.parseJSON(data)

트릭을해야합니다. 이것은 물론 적절한 형식의 json 문자열을 갖는 것 외에도 ..


6

json 응답을 에코하고 헤더가 * / json과 일치하지 않으면 내장 된 jQuery.parseJSON API를 사용하여 응답을 구문 분석 할 수 있습니다.

response = '{"name":"John"}';
var obj = jQuery.parseJSON(response);
alert( obj.name === "John" );

4
{ title: "One", key: "1" }

당신이 생각하는 것이 아닙니다. 표현식 으로서는 객체 리터럴이지만 명령문으로는 다음과 같습니다.

{                // new block
    title:       // define a label called 'title' for goto statements
        "One",   // statement: the start of an expression which will be ignored
        key:     // ...er, what? you can't have a goto label in the middle of an expression
                 // ERROR

안타깝게도 eval ()은 명령문인지 표현식인지 지정하는 방법을 제공하지 않으며 잘못 추측하는 경향이 있습니다.

일반적인 해결책은 실제로 eval () 함수로 보내기 전에 괄호 로 묶는 입니다. 서버에서 시도해 봤다고 하셨는데 ... 분명히 통과가 안되네요. XMLHttpRequest 응답을받는 것이 무엇이든 클라이언트 측에서 말할 수 있어야합니다.

eval('('+responseText+')');

대신에:

eval(responseText);

응답이 실제로 진술이 아닌 표현이면됩니다. (예 : 세미콜론 또는 줄 바꿈으로 구분 된 여러 절이 없습니다.)


요청 데이터를 처리 할 때 jQuery가 자동으로 괄호를 추가한다고 생각합니다.
strager

2
이 답변은 사람들이 JSON을 괄호로 묶는 이유를 결코 이해하지 못했기 때문에 나에게 매우 도움이되었습니다.
Andrey Tarantsov


2

jQuery를 사용하여 ASP.NET 웹 서비스를 사용하는 경우 web.config에 다음이 포함되어 있는지 확인하십시오.

<webServices>
    <protocols>
        <add name="HttpGet"/>
        <add name="HttpPost"/>
    </protocols>
</webServices>

2

Firefox 3.5가 제대로 작동하고 JSON 데이터를 구문 분석했지만 Firefox 3.0.6이 구문 분석 오류를 반환하는 유사한 문제가 발생했습니다. Firefox 3.0.6에서 오류가 발생하는 원인은 JSON 시작 부분의 공백이었습니다. 빈 공간을 제거하여 수정


2

"eval ()"및 "JSON.parse ()"기술은 상호 배타적 인 형식을 사용합니다.

  • "eval ()"괄호가 필요합니다 .
  • "JSON.parse ()"괄호는 금지되어 있습니다.

"eval"형식을 생성하는 "stringify ()"함수가 있습니다. ajax의 경우 JSON 형식 만 사용해야합니다.

"eval"은 전체 JavaScript 언어를 통합하지만 JSON은 언어의 일부만 사용합니다. "eval"이 인식해야하는 JavaScript 언어의 구조 중에는 "Block 문"(일명 "복합 문")이 있습니다 . 내부에 일부 명령문이있는 쌍 또는 중괄호 "{}"입니다. 그러나 중괄호는 객체 리터럴의 구문에도 사용됩니다. 해석은 코드가 나타나는 컨텍스트에 따라 다릅니다. 어떤 것이 당신에게 객체 리터럴처럼 보일 수 있지만 "eval"은 그것을 복합 문으로 볼 것입니다.

JavaScript 언어에서 객체 리터럴은 할당 오른쪽에 나타납니다.

var myObj = { ...some..code..here... };

객체 리터럴은 자체적으로 발생하지 않습니다.

{ ...some..code..here... }   // this looks like a compound statement

2008 년에 질문했던 OP의 원래 질문으로 돌아가서 그는 "eval ()"에서 다음이 실패한 이유를 물었습니다.

{ title: "One", key: "1" }

대답은 그것이 복합 문처럼 보인다는 것입니다. 객체로 변환하려면 복합 문이 불가능한 컨텍스트에 넣어야합니다. 주위에 괄호를 넣어서

( { title: "One", key: "1" } )    // not a compound statment, so must be object literal

OP는 또한 유사한 진술 성공적으로 평가 된 이유를 물었습니다 .

[ { title: "One", key: "1" }, { title: "Two", key: "2" } ]

동일한 대답이 적용됩니다. 중괄호는 복합 명령문이 불가능한 컨텍스트에 있습니다. 이것은 배열 컨텍스트 인 " [...]"이며 배열은 객체를 포함 할 수 있지만 명령문은 포함 할 수 없습니다.

"eval ()"과 달리 JSON은 그 기능이 매우 제한적입니다. 제한은 의도적입니다. JSON 디자이너는 할당의 오른쪽에 나타날 수있는 구문 만 사용하여 JavaScript의 최소한의 하위 집합을 의도했습니다. 따라서 JSON에서 올바르게 구문 분석하는 코드가 있다면 ...

var myVar = JSON.parse("...some...code...here...");

... 이는 이와 같이 할당의 오른쪽에서도 합법적으로 구문 분석 할 것임을 의미합니다.

var myVar = ...some..code..here... ;

그러나 이것이 JSON에 대한 유일한 제한은 아닙니다. JSON에 대한 BNF 언어 사양은 매우 간단합니다. 예를 들어, 문자열을 나타 내기 위해 작은 따옴표를 사용할 수 없으며 (JavaScript 및 Perl처럼) 단일 문자를 바이트로 표현하는 방법이 없습니다 ( 'C'처럼). 불행히도 주석도 허용하지 않습니다 (구성 파일을 만들 때 정말 좋을 것입니다). 이러한 모든 제한의 장점은 JSON 구문 분석이 빠르고 코드 삽입 (보안 위협)의 기회를 제공하지 않는다는 것입니다.

이러한 제한으로 인해 JSON은 괄호를 사용하지 않습니다. 따라서 JSON 문자열의 괄호는 잘못된 문자입니다.

다음과 같은 이유로 항상 ajax와 함께 JSON 형식을 사용합니다.

  • 일반적인 ajax 파이프 라인은 JSON 용으로 구성됩니다.
  • "eval ()"의 사용은 보안 위험으로 비판 될 것입니다.

ajax 파이프 라인의 예로 Node 서버와 jQuery 클라이언트를 포함하는 프로그램을 고려하십시오. 클라이언트 프로그램은 형식이있는 jQuery 호출을 사용합니다 $.ajax({dataType:'json',...etc.});. JQuery는 나중에 사용하기 위해 jqXHR 객체를 생성 한 다음 관련 요청을 패키징하고 보냅니다. 서버는 요청을 수락하고 처리 한 다음 응답 할 준비가됩니다. 서버 프로그램은 res.json(data)응답을 패키징하고 전송하기 위해 메서드 를 호출합니다 . 클라이언트 측으로 돌아가서 jQuery는 응답을 수락하고 연관된 jqXHR 객체를 참조하고 JSON 형식 데이터를 처리합니다. 이 모든 것이 수동 데이터 변환없이 작동합니다. 응답에는 Node 서버에서 JSON.stringify ()에 대한 명시 적 호출과 클라이언트에서 JSON.parse ()에 대한 명시 적 호출이 포함되지 않습니다. 그게 모두 당신을 위해 처리됩니다.

"eval"의 사용은 코드 삽입 보안 위험과 관련이 있습니다. 일어날 수있는 방법이 없다고 생각할 수도 있지만 해커는 상당히 창의적 일 수 있습니다. 또한 "eval"은 Javascript 최적화에 문제가 있습니다.

"stringify ()"함수를 사용하는 경우 해당 이름을 가진 일부 함수는 JSON이 아닌 "eval"과 호환되는 문자열을 생성한다는 점에 유의하십시오. 예를 들어, Node에서 다음은 "eval"호환 형식으로 문자열을 생성하는 함수를 제공합니다.

var stringify = require('node-stringify'); // generates eval() format

이것은 유용 할 수 있지만 특별한 필요가 없다면 아마도 원하는 것이 아닐 것입니다.


1

배열 반환이 작동하고 단일 객체 반환이 작동하지 않는 경우 단일 객체를 해당 단일 객체를 포함하는 배열로 반환 할 수도 있습니다.

[ { title: "One", key: "1" } ]

이렇게하면 데이터 페이로드에 관계없이 일관된 데이터 구조, 객체 배열을 반환합니다.

단일 개체를 "괄호"로 래핑하려고 시도했으며 JavaScript가 [..]를 (..)와 다르게 취급하므로 예제와 함께이를 제안했습니다.


1

jQuery의 오류 처리기가 호출되고 XHR 개체에 "파서 오류"가 포함되어있는 경우 서버에서 돌아 오는 파서 오류 일 수 있습니다.

매개 변수없이 서비스를 호출 할 때 여러 결과 시나리오가 발생하지만 단일 레코드를 검색하기 위해 매개 변수를 제공하려고하면 중단됩니까?

이걸 반환하는 백엔드는 무엇입니까?

예를 들어 ASMX 서비스에서 매개 변수가 JSON 문자열 대신 JSON 객체로 jQuery에 제공되는 경우가 많습니다. jQuery에 "data"매개 변수에 대한 실제 JSON 객체를 제공하면 JSON으로 전송하는 대신 표준 및 구분 된 k, v 쌍으로 직렬화합니다.


1

추가해야 할 일부 구현에서 발견했습니다.

obj = new Object; obj = (data.obj);

문제를 해결하는 것 같았습니다. Eval이든 아니든 그것은 나에게 똑같은 일을하는 것 같았습니다.


Object 생성자가 아닌 새 객체를 초기화 할 때 객체 리터럴을 사용합니다. var obj = {};
Andreas Grech

그래요, var myArray = [] for arrays 및 var myObject = {}, 팁 감사합니다 Dreas
Jay

1

jQuery는 특정 JSON 키에서 질식합니다. 이 JSON 스 니펫을 PHP로 보냈습니다.

echo json_encode((object) array('result' => 'success'));

'결과'키의 이름을 다른 것으로 바꾸면 작동합니다. 나는 이것이 일종의 예약어 충돌이며 jQuery (1.4.2)의 버그 일 수 있다고 생각합니다.


1

ColdFusion 환경에서 올바른 형식의 JSON을 사용하더라도 오류를 발생시키는 한 가지는 사용 ColdFusion Administrator (디버깅 및 로깅> 디버그 출력 설정 아래)에서 디버깅 출력 요청 활성화를 설정하는 것입니다. 디버깅 정보는 JSON 데이터와 함께 반환되므로 유효하지 않게됩니다.


1

또한 이것을 시도하십시오

$.ajax({
    url: url,
    data:datas,
    success:function(datas, textStatus, jqXHR){
    var returnedData = jQuery.parseJSON(datas.substr(datas.indexOf('{')));
})};

제 경우에는 서버가 '{'앞에 알 수없는 문자로 응답합니다.


1

상태 = parseerror 및 xhr.status = 200을 얻었습니다.

나에게 문제는 JSON 응답 내부의 URL이 '\'가 '/'로 전환되어이 문제를 해결했다는 것입니다.


0

나는 이것으로 어려움을 겪고 있었고, 방화범을 사용하여 데이터 개체를 표시 할 때까지 이것을 알아 내기 위해 몇 시간을 보냈다.

var data = eval("(" + data.responseText + ")");
console.log(data.count);

-1

사용하다

$data = yourarray(); 
json_encode($data)

서버 측에서. 클라이언트 측에서는 데이터 유형 JSON과 함께 ajax를 사용하고 문서 인코딩이 BOM이있는 UTF-8이 아닌지 확인하십시오. UTF-8이어야합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.