Perl Catalyst -从AJAX POST请求中获取JSON数据

n3schb8v  于 12个月前  发布在  Perl
关注(0)|答案(3)|浏览(138)

我试图获取JSON数据,当在我的Catalyst应用程序的homescreen页面上单击按钮时,JSON数据通过AJAX POST发送到服务器:
将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'
});

我还有以下用于homescreen页面的Catalyst控制器,发送AJAX POST的按钮位于该页面上:

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或其他名称)

gpfsuwkq

gpfsuwkq1#

虽然内置的日志工具在你制作持久化日志和分析日志时很有用,但我发现它并不适合用于基本的调试。我最近一直在使用Devel::Dwarn,它很容易安装。这就像一个警告转储程序+非常整齐地卷起来。
如果你像这样启动你的应用程序

perl -MDevel::Dwarn ...

你可以粘贴Dwarn $ref并得到一个漂亮的stderr输出:

Dwarn $c->req->body_data

给予给你一个简洁的回顾,另外如果你把-MDevel::Dwarn掉了,你会在所有你不小心漏掉了Dwarn的地方得到错误(这是我上个月在Runner 002的borked版本中应该做的)。
如果这让你感到困惑,试试看:
cpanm Devel::Dwarn之后)

use Devel::Dwarn;
Dwarn $c->req->body_data

你应该得到一个深层结构输出到你的控制台。祝你好运!

xcitsw88

xcitsw882#

  • 我的另一个答案是(希望)对任何调试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){ ... }
    });
});

我希望这一切都能让你更清楚地知道你要做什么。

hpxqektj

hpxqektj3#

您的Catalyst应用程序不会接收JSON。dataType参数告诉$.ajax()如何 * 解析 * 从服务器返回的数据。发送到服务器的是带有HTML表单参数的bog标准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包含一个hash(毫不奇怪),它有一个键stateForUserNumber7,包含一个hash数组的引用,这就是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进行调试。

相关问题