类型转换perl,javascript,JSON.parse JSON :: XS - 需要创意

时间:2012-02-12 20:25:02

标签: javascript json perl

我遇到了问题,我正在寻找有关解决问题的最佳方法的想法。

我已经开始开发一个网站,其中后端是用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;
}   

}

1 个答案:

答案 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]