【问题标题】:type conversion perl, javascript, JSON.parse JSON::XS - need ideas类型转换 perl, javascript, JSON.parse JSON::XS - 需要想法
【发布时间】:2012-03-04 08:57:14
【问题描述】:

我遇到了一个问题,正在寻找解决问题的最佳方法。

我接手开发了一个网站,其中后端是用 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 只是将数字数据解析为字符串而不是数字。我试图向 JSON.parse 添加一个 reviver(参见下面的代码) - 但是它不起作用(它正确处理大部分数据,但由于各种消息(例如 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;
}   

}

【问题讨论】:

  • 啊 - 我刚刚修好了我的复活器,它必须如下; function toNum(key, value) { /*确保 value 包含整数或浮点数而不是字符串 */ /*TODO: 这似乎非常低效 - 有没有更好的方法 */ if (value instanceof String) { var intRE = /^\d+$/; var floatRE = /^\d*\.\d+$/; if(value.match(intRE)) { value = parseInt(value);返回值; } if(value.match(floatRE)) { value = parseFloat(value);返回值; } } else { 返回值; } } 但如果存在,仍然希望找到更好的方法?
  • 好的,事实证明,在服务器端解决此问题的唯一方法(我能找到)是解析数据对象,查找任何看起来像整数或浮点数的东西并添加 0给它。即 $val += 0。然后我在 JS 端得到正确的值。

标签: javascript json perl


【解决方案1】:

简单的 Perl 标量(任何不是引用的标量)是最难编码的对象:JSON::XS 和 JSON::PP 会将未定义的标量编码为 JSON 空值,即最后在字符串中使用的标量编码为 JSON 字符串之前的上下文,以及其他任何数字值...

诀窍是在编码之前将要编码为数字的任何值“数字化”。

$ perl -MJSON -e '$x="5"; print JSON->new->encode( [ $x, "$x", 0+$x ] )'
["5","5",5]

【讨论】:

  • 是的。只要在这样做和 JSON 编码之间不编写任何将这些成员视为字符串的代码,您就可以对您的数据结构执行此操作(例如$data->{member} += 0)。从技术上讲,您希望您的数据是!SvPOK
  • 认为当从内存缓存或数据库中检索对象时,它们(有时)被视为字符串 - 这听起来可能吗?这是我能找到的唯一可能发生转换的地方。
猜你喜欢
  • 1970-01-01
  • 2017-03-28
  • 2019-02-21
  • 2011-12-20
  • 2013-06-28
  • 2016-05-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多