[英]Perl Catalyst - Obtaining JSON data from AJAX POST request
當在我的 Catalyst 應用程序的homescreen
頁面上單擊按鈕時,我試圖獲取通過 AJAX POST 發送到服務器的 JSON 數據:
將 JSON 數據發送到服務器的 AJAX POST:
$("#saveCanvasStates").click(function () {
// button to save canvas states to a database
// Serialize the states array
var JsonStringForTransport = JSON.stringify({stateForUserNumber7: states});
// POST the JSON to the server
var thePost = $.ajax({
url: 'homescreen',
type: 'POST',
dataType: 'json',
data: JsonStringForTransport,
contentType: 'application/json; charset=utf-8'
});
我還有以下用於發送 AJAX POST 的按鈕所在的homescreen
頁面的 Catalyst 控制器:
催化劑控制器:
package MyProject::Controller::Homescreen;
use strict;
use warnings;
use parent 'Catalyst::Controller';
use Data::Dumper;
__PACKAGE__->config->{namespace} = '';
sub homescreen :Path('/homescreen') :Args(0) {
my ( $self, $c ) = @_;
$c->stash({title => 'Home Screen',
pagetype => 'html',
template => 'homescreen.html'
});
#here is where I think I need to obtain the JSON data from the AJAX POST request
#and save it to my database
}
1;
一旦我以一種可以使用的形式獲得了這個 JSON 數據,我就會將它保存到 Postgres 數據庫中。
通過查看Catalyst::Request的 CPAN 文檔,根據我的理解,這是在處理請求內容時所指的內容,可以使用以下內容來處理 AJAX POST 數據?:
但我不確定將數據轉換為表單的最佳方法,然后我可以將其插入到我的數據庫中,以及應該優先使用哪一種方法?
我幾乎找不到對我有幫助的文檔。
我肯定有要顯示的body_data
因為當我這樣做時:
print Dumper($c->req->body_data);
我在我的開發服務器日志中打印了以下內容:
$VAR1 = {
'stateForUserNumber7' => [
{
'width' => 102,
'offsetY' => 56,
'x' => 11,
'height' => 102,
'image' => {},
'y' => 14,
'contextIndex' => 2,
'dragging' => bless( do{\(my $o = 0)}, 'Cpanel::JSON::XS::Boolean' ),
'offsetX' => 73
},
{
'width' => 102,
'offsetY' => 34,
'x' => 103,
'height' => 102,
'image' => {},
'y' => 17,
'contextIndex' => 3,
'dragging' => $VAR1->{'stateForUserNumber7'}[0]{'dragging'},
'offsetX' => 46
}
]
};
[info] *** Request 15 (1.250/s) [17427] [Fri Dec 6 00:02:22 2013] ***
[debug] Path is "homescreen"
[debug] "POST" request for "homescreen" from "192.168.1.100"
[debug] Rendering template "homescreen.html"
[debug] Response Code: 200; Content-Type: text/html; charset=utf-8; Content-Length: 7010
[info] Request took 0.025343s (39.459/s)
.------------------------------------------------------------+-----------.
| Action | Time |
+------------------------------------------------------------+-----------+
| /homescreen | 0.014044s |
| /end | 0.001992s |
| -> Organiser::View::TT->process | 0.001058s |
'------------------------------------------------------------+-----------'
這是它在使用-d
時在開發服務器輸出中給出的錯誤:
Caught exception in Organiser::Controller::Homescreen->homescreen "Can't use an undefined value as a HASH reference at /home/fred/Organiser/script/../lib/Organiser/Controller/Homescreen.pm line 21."
這是我在運行開發服務器時從 Stack Trace 得到的錯誤:
Stack Trace
Package Line File
Organiser::Controller::Homescreen 21 /home/fred/Organiser/lib/Organiser/Controller/Homescreen.pm
18:
19: print STDERR Dumper $c->req->body_data;
20:
21: foreach my $data (@{$c->req->body_data->{stateForUserNumber7}}) { <-- it highlights in bold this line
22: print "DOLLAR DATA $data\n";
23: }
24:
Organiser::Controller::Root 17 /home/fred/Organiser/lib/Organiser/Controller/Root.pm
14: sub index :Path :Args(0) {
15: my ( $self, $c ) = @_;
16:
17: $c->forward('homescreen'); <-- it highlights in bold this line
18:
19: }
20:
使用 Firebug 這是正在發生的 POST 請求(在我注釋掉導致錯誤的 foreach 之后)
Source
{"stateForUserNumber7":[{"dragging":false,"contextIndex":4,"image":{},"x":108,"y":4,"width":102,"height":102,"offsetX":45,"offsetY":65}]}
它始終是stateForUserNumber7
(我應該將其命名為 master_user 或其他名稱)
盡管當您將日志持久化並進行分析時,內置的日志記錄功能非常棒,但我發現它在基本調試中的使用並不是很糟糕。 我最近一直在使用易於安裝的 Devel::Dwarn。 這就像一個警告自卸車+卷得很整齊。
如果你像這樣啟動你的應用程序
perl -MDevel::Dwarn ...
你可以堅持Dwarn $ref
並獲得一個不錯的 stderr 輸出:
Dwarn $c->req->body_data
應該給你一個整潔的評論。 另外,如果你放棄-MDevel::Dwarn
你會在所有你不小心遺漏Dwarn
的地方Dwarn
(我應該在上個月發布的 Runner 002 中做這件事)。
如果這讓您感到困惑,請嘗試:
(在cpanm Devel::Dwarn
)
use Devel::Dwarn;
Dwarn $c->req->body_data
你應該得到一個深層結構輸出到你的控制台。 祝你好運!
我的另一個答案是(希望)對調試 Catalyst/JSON 問題的任何人有用的信息。 但是對該問題的后續更新表明這里的問題實際上是完全不同的。
此處沒有足夠的操作來支持所需的功能。 如果index
操作轉發到呈現homescreen.html
模板的homescreen
操作,則$.json()
調用必須是其他一些負責處理數據保存請求的操作,而不是其他操作。
package MyProject::Controller::Homescreen;
use strict;
use warnings;
use parent 'Catalyst::Controller';
use JSON;
sub homescreen :Path('/homescreen') :Args(0) {
my ( $self, $c ) = @_;
$c->stash({title => 'Home Screen',
pagetype => 'html',
template => 'homescreen.html'
});
}
sub savecanvasstates :Local {
my ($self, $c, @args) = @_;
my $p = $c->req->param->{stateForUserNumber7} || die "wrong parameters!";
my $result = {};
foreach my $r (@{$p}) {
# ... do something with $r->{x} etc
$result->{output} = # construct whatever object the ajax caller expects
}
$c->res->body(to_json($result))
}
1;
在附近的一些 JavaScript 中:
$("#saveCanvasStates").click(function () {
// button to save canvas states to a database
// Serialize the states array
var JsonStringForTransport = JSON.stringify({stateForUserNumber7: states});
// POST the JSON to the server
var thePost = $.ajax({
url: 'savecanvasstates',
type: 'POST',
dataType: 'json',
data: JsonStringForTransport,
contentType: 'application/json; charset=utf-8',
success: function(data, textStatus){ ... }
error: function(XMLHttpRequest, textStatus, errorThrown){ ... }
});
});
我希望所有這些都使您必須做的事情更加清楚。
您的 Catalyst 應用程序不會收到 JSON。 dataType
參數告訴$.ajax()
如何解析從服務器返回的數據。 發送到服務器的是帶有 HTML 表單參數的沼澤標准 GET 或 POST 請求。
當 Catalyst 收到它們時,它們是$c->req->params
普通舊鍵,非常適合您想要啟動的任何數據庫操作。
所以如果
/* JS */
JsonStringForTransport = { foo: "bar", baz: "quux" };
然后在 Catalyst 端,您將收到:
# perl
my $foo = $c->req->params->{foo}; # or $c->req->body_params->{foo}
if ($c->req->params->{baz} eq "quux"){ ... }
……等等。
更新
所以body_data
包含一個散列( body_data
),它有一個鍵stateForUserNumber7
,其中包含對散列數組的引用。 這就是 Dumper 輸出告訴你的。
您應該能夠使用以下方法訪問body_data
:
my $first_x = $c->req->body_data->{stateForUserNumber7}->[0]->{x};
print STDERR "first_x = $first_x\n"; # should print first_x = 11
但是,您更有可能想要執行以下操作:
foreach my $data (@{$c->req->body_data->{stateForUserNumber7}}) {
# do something with $data->{x}, $data->{y}, $data->{height} etc
}
更新
jnap在2013 Catalyst Advent Calendar發表了一篇關於如何使用body_data
的非常好的文章。 如果您在您的應用程序中使用此功能而不是更傳統的params
,您絕對應該花時間閱讀和吸收它。
更新
抱歉,之前對dataType
,所以我已經更正了。 但這並沒有改變我的答案的基本原理。
我認為您將不得不內省您的body_data
以找出出了什么問題。 它總是“stateForUserNumber7”,還是因請求而異? 有什么作用
$c->log->debug("body_params keys: " _ join(", ", keys %{ $c->req->body_data }));
生產?
您必須使用開發服務器(即bin/myapp_server.pl
),以便獲得完整的調試輸出來幫助您。 根本不推薦通過 Apache 或 FastCGI 進行調試。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.