質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.37%

ajaxの戻り値にqが付くのはなぜ?

解決済

回答 4

投稿

  • 評価
  • クリップ 2
  • VIEW 2,822

score 3

端末側 HTML+JavaScript+jQuery
サーバー側 PHP

jQuery ajax で質問です

端末側(JavaScript)
return $.ajax({
type: "GET"
, dataType: 'json'
}).done(function (result) {
return result;

}).fail(function (xhr, textStatus, errorThrown) {
alert(xhr);
return "";
});

サーバー側(PHP)
header('Content-Type: application/javascript; charset=utf-8');
echo json_encode( $_jsonArray );

JSON文字列は返っているようですが、返ってきた文字列がqで囲まれて
端末側でparseerrorとなり、status:200になります

試しにプレーンテキストで "HOGE"という文字列を返してみましたが
やはり q がくっついた状態になります

ブラウザはChrome、サーバー側としてATOMを使用しています。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • defghi1977

    2018/03/21 04:09

    ああ, やっぱりそれJSONじゃなくてJSONPだよ

    キャンセル

  • SurferOnWww

    2018/03/21 12:30

    JSONP でコールバック名が q ということですね。たぶん JSONP とするのは質問者さんの望むことではなく、普通に JSON をやり取りしたいのだと思いますが、そうであればサーバー側の実装をそのように変えてください。そうすれば jQuery ajax のコードはそのままで OK のはずです。

    キャンセル

  • SurferOnWww

    2018/03/21 12:33

    サーバー側は今の実装のまま、即ち JSONP としたいということであれば、jQuery ajax のコードに若干の変更をすれば解決できると思います。それを回答欄に追記しておきます。

    キャンセル

回答 4

+4

勘違いかもしれませんがapiが基本的にjsonp形式で返してくる仕組みなのでは?
「qで囲まれている」というあいまいな表現がすべてを混乱させている原因だと思います
ふつうqで囲むとは戻り値が
q{abc:123}q
のようなことですよね

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

checkベストアンサー

+3

あなたがJSONと表現していたそれは, 実際にはJSONP(JSONをscript要素を使ってクロスドメインで入手するテクニック)と呼ばれているものです.

例を示します.

まず, 次のようなコールバック関数を定義したとしましょう.

window.q = function(data){
  console.log(data.name);
}

ここでhttp://jsonp.comにアクセスすると次のようなスクリプトが返されるものとします.

q(
  {
    "name": "ななしのごんべえ"
  }
)


これはあなたがJSONにqがくっついていると表現したものですが, 実際にはグローバル関数qにJSONを引数として渡しているのです.

そこで次のようなコードを実行しましょう.

const script = document.createElement("script");
script.src = "http://jsonp.com";
document.body.appendChild(script);


すると, 次の処理フローが発生します.

  1. script要素がDOMに追加され, http://jsonp.comに対するリクエストが飛ぶ.
  2. http://jsonp.comからはJSONPが返され, その内容が実行される.
  3. その中でグローバル関数(コールバック関数)qが呼び出され, 結果としてJSONの内容を取り出すことができる.

つまりコンソールにはななしのごんべえと出力されることでしょう.

NOTE:
この仕組みはscript要素の特性(原則クロスドメインでのアクセスが可能)上, コールバック関数の名称さえ分かればどこからでも利用できます. そのため本質的にリスクを伴う(今回のように単なるJSONもどきと考えるのは論外である)点に注意して下さい. 


q( ... JSON 文字列 ... ) になります。(JSON文字列にはお客様情報が含まれているので、具体例はご容赦ください) 

我々が言いたかったのはこの構造のサンプルを提示してほしかったのであって, JSONそのものに興味はありません. ですから今後このようなリクエストがあった場合は, (JSONの等の)構造の中身を適宜ダミーデータに書き換えたものを質問に含めるようにして下さい.

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/03/21 05:30

    ありがとうございます。
    すぐには試すことができない状況ですが、後日試してみます。

    キャンセル

  • 2018/03/21 13:31

    質問者さんは jQuery ajax を使っているようですので、script 要素を追加するために自力で JavaScript のコードを書いて対処するより、そこは jQuery ajax に任せた方がよさそうだと思います。

    キャンセル

+3

PHP は知らないのでハズレかもしれませんが・・・

JSON文字列は返っているようですが、返ってきた文字列がqで囲まれて

セキュリティ対策で JSON 応答が "q" でラップされているということはないでしょうか?

JSON サービスの脆弱性(JSON 配列は JavaScript として有効)に起因する XSS 対策として、ASP.NET の Web サービスの JSON 応答は .NET 3.5 から "d" でラップされるようになりました。WCF も同様です。

それと同様な話ということはないでしょうか?

ASP.NET Web サービスで jQuery ajax を使う場合は、そのラップを外すコーディングを追加する必要があります。例えば "d" でラップされる場合は以下のようになります。

success: function (data) {
    if (data.hasOwnProperty('d')) {
        data = data.d;
    }

    // data の処置
}

ハズレでしたらすみません。もし、上記の話の詳しい説明に興味がありましたら以下の記事を見てください。

jQuery AJAX と Web サービス
http://surferonwww.info/BlogEngine/post/2011/06/04/jQuery-AJAX-and-Web-Service.aspx

WCF と jQuery AJAX
http://surferonwww.info/BlogEngine/post/2015/10/15/wcf-and-jquery-ajax.aspx

【2018/3/21 13:20 追記】

質問に対する 2018/03/21 12:33 の私のコメントで「サーバー側は今の実装のまま、即ち JSONP としたいということであれば、jQuery ajax のコードに若干の変更をすれば解決できると思います。それを回答欄に追記しておきます」と書きましたが、それを以下に書きます。

JSONP でコールバック名が q すなわち q( ... JSON 文字列 ... ) という応答が返ってくる場合(コールバック名は q で固定と理解)、jQuery ajax のパラメータを以下のようにします。

$.ajax({
    url: xxxx,
    dataType: 'jsonp',
    jsonp: false,
    jsonpCallback: 'q'
 }).done(function (result) {
    ・・・以下略・・・

xxxx は要求先の URL です。

dataType: 'jsonp' とすると、jQuery.ajax を呼び出した時点で script タグを生成し DOM ツリーへ追加してくれます。(script タグを生成して DOM ツリーに追加するためのスクリプトを自力で書く必要はありません) 

コールバック名を q とする、すなわち q( ... JSON 文字列 ... ) という応答が返ってくる場合は jsonp: false, jsonpCallback: 'q' と設定します。

応答が返ってくるとコールバックが呼び出され、コールバックの引数に設定された JSON 文字列が JavaScript オブジェクトにパースされ、done(function (result) { ... の result に渡されます。 

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/03/17 11:58

    error の方のコールバックに飛ぶということですと、q でラップされているということではなさそうですね。Fiddler などのキャプチャツールを使って、どういう応答が返ってきているか調べてみることをお勧めします。それでかなりのことが分かるのではないかと思われます。

    キャンセル

  • 2018/03/17 12:02

    あと error のコールバックを function (jqXHR, textStatus, errorThrown) { ... } のようにして、textStatus, errorThrown がどうなっているかも調べてください。それにも問題解決に有用な情報が含まれていると思います。

    キャンセル

  • 2018/03/17 13:44

    Fiddler が何かは以下の記事を見てください。Chrome のディベロッペパーツール、IE の F12 開発者ツールでもキャプチャできますが、Fiddler が使いやすいので自分的にはお勧めです。IE, Firefox, Chrome いずれにも使えます。

    Fiddler のお勧め
    http://surferonwww.info/BlogEngine/post/2011/05/25/Recommendation-of-Fiddler.aspx

    上の記事の画像(クリックすると拡大画像が表示されます)の右下のウィンドウで TextView にすると、応答とした返ってきた JSON 文字列がどうなっているかが分かります。

    キャンセル

+1

以下の部分ですが…

}).done(function (result) {
return result;

})

ajaxは非同期処理なので、return result; としても戻り値を受け取れません。ここに処理の中身を書けば正常に値を受け取れると思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/03/17 11:51

    同期にするために async: false を設定してます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.37%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る