我遇到了问题,我正在寻找有关解决问题的最佳方法的想法。
我已经开始开发一个网站,其中后端是用Perl编写的,而前端则广泛使用了javascript。
客户端定期从后端接收数百个跟踪对象的更新。通过javascript将对象映射到谷歌地图上。对象散列(由javascript解析)包含有关对象的大量信息,例如位置,描述和各种状态变量 一些数据是字符串形式和一些数字。
问题是,在将数据推送到客户端javascript的过程中,所有值都成为字符串。因此,在javascript中,如果我测试一下,看看值是否为正,即使值为0,测试也会成功,因为该值实际上是" 0"不是0.
在服务器端,数据使用JSON :: XS编码,如下所示;
sub process_json {
my $self = shift;
return if( $self->{processed} );
$self->{processed} = 1;
if( $self->{requestrec}->status =~ /^3/ )
{
return $self->{requestrec}->status;
}
$self->{data}->{session} = {
id => $self->session->id,
user => $self->session->{data}->{__user},
};
use utf8;
my $output;
eval { $output = JSON::XS->new->utf8->encode( $self->{data} ); };
if($@)
{
use Carp;
confess($@);
}
$self->discard_request_body();
$self->req->content_type('application/json; charset=utf-8');
$self->req->headers_out->set( 'Expires' => 'Thu, 1 Jan 1970 00:00:00 GMT' );
my $out_bytes = encode( 'UTF-8', $output );
$self->req->headers_out->set( 'Content-Length' => length $output );
$self->req->print($output) unless( $self->req->header_only() );
delete $self->{session}->{data}->{errors}
if( exists $self->{session}->{data}->{errors} );
delete $self->{session}->{data}->{info}
if( exists $self->{session}->{data}->{info} );
} ## end of: sub process_json
在客户端,数据使用JSON.parse进行解码,如下所示;
function http_process (req, callback, errorfn) {
if (req.readyState == 4) {
this.activerequest = null;
if (req.status != 200 && req.status != 0 && req.status != 304 && req.status != 403) {
if (errorfn) { return errorfn(req); } else { dialogue("Server error", "Server error " + req.status); }
if (req.status == 400) { dialogue("ERROR","Session expired"); this.failed = 1;
} else if (req.status == 404) { dialogue("ERROR", "Server error (404)"); this.failed = 1;
} else if (req.status == 500) { dialogue("ERROR", "Server error (500)"); this.failed = 1; }
} else {
if (callback) {
if (req.responseText) {
lstatus("Loaded (" + req.responseText.length + " bytes)");
warn("Received " + req.responseText.length + " bytes");
try {
var obj = JSON.parse(req.responseText);
} catch(e) {
warn(e);
warn(req.responseText);
}
callback( obj );
} else {
callback({});
}
}
}
}
}
有人能看到解决这个问题的有效方法吗? Perl不是强类型的,JSON :: XS只是将数字数据解析为字符串而不是数字。我试图将一个reviver添加到JSON.parse(参见下面的代码) - 但是它不起作用(它正确处理大部分数据但是使用各种消息失败,例如non_object_property_call或undefined_method。
如果在服务器端处理解析数据以确保正确类型的工作,那将是更好的选择。任何人都可以看到如何有效地实现这一目标吗?
function toNum(key, value) {
/*make sure value contains an integer or a float not a string */
/*TODO: This seems VERY inefficient - is there a better way */
if (value instanceof Object) return;
if (value instanceof Array) return;
var intRE = /^\d+$/;
var floatRE = /^\d*\.\d+$/;
if(value.match(intRE)) {
value = parseInt(value);
return value;
}
if(value.match(floatRE)) {
value = parseFloat(value);
return value;
}
}
答案 0 :(得分:7)
简单的Perl标量(任何不是引用的标量)是最难编码的对象:JSON :: XS和JSON :: PP会将未定义的标量编码为JSON空值,最后在字符串中使用的标量编码为JSON字符串之前的上下文,以及其他任何数字值......
诀窍是在编码之前将要编码的任何值“编号”为数字。
$ perl -MJSON -e '$x="5"; print JSON->new->encode( [ $x, "$x", 0+$x ] )'
["5","5",5]