簡體   English   中英

Perl Catalyst - 從 AJAX POST 請求中獲取 JSON 數據

[英]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 數據?:

  • $c->$req->body_data
  • $c->$req->body_parameters
  • $c->$req->body_params

但我不確定將數據轉換為表單的最佳方法,然后我可以將其插入到我的數據庫中,以及應該優先使用哪一種方法?

我幾乎找不到對我有幫助的文檔。

更新(與 RET 的回答有關)

我肯定有要顯示的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
}

更新

jnap2013 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM