2012-02-12 5 views
7

私は問題に悩まされています。私はそれに取り組むための最善の方法に関するアイデアを探しています。タイプ変換perl、javascript、JSON.parse JSON :: XS - アイデアが必要です

私は、バックエンドがPerlで書かれたサイトの開発を引き継いでおり、フロントエンドはJavaScriptを大量に使用しています。

クライアントは定期的にバックエンドから数百個の追跡対象オブジェクトの更新を受け取ります。オブジェクトはjavascript経由でGoogleマップにマッピングされます。オブジェクトのハッシュ(javascriptによって解析される)には、オブジェクトに関する多くの情報が含まれています。位置、説明、および様々な状態変数を含む。
データの一部は文字列形式で、数値があります。

問題は、データをクライアントサイドのJavaScriptにプッシュする過程で、すべての値が文字列になりつつあることです。そして、javascriptでは、私が例としてテストすると、値が正であるかどうかを調べるために値が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([email protected]) 
{ 
    use Carp; 
    confess([email protected]); 
} 

$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

Ah - 私はリバイバーを固定しました。次のようにしなければなりませんでした。 ファンクションtoNum(キー、値){ \t/*値は、整数または浮動小数点数ではない文字列*/ \t/* TODOが含まれていることを確認してください。これは非常に非効率です - */ \tより良い方法があればそこにある(値instanceof String){ \t \t var intRE =/^ \ d + $ /; \t \t var floatRE =/^¥d*\.\d+$/; if(value。一致(intRE)){ \t \t \t値= parseInt(値); \t \t \t戻り値; \t \t} \t \t IF(value.match(floatRE)){ \t \t \t値= parseFloatは(値)。 \t \t \t戻り値;他 \t \t} \t \t \t \t} \t { \t \t戻り値; \t} } しかし、まだ存在すればもっと良い方法を見つけるのが好きですか? – mark

+0

OK、サーバー側でこれを修正する唯一の方法は、データオブジェクトを解析し、integrerやfloatのようなものを探し、0を追加することです。つまり$ val + = 0. JS側で正しい値が得られます。 – mark

答えて

7

シンプルなPerlのスカラー(スカラーは参照ではありません)は最も難しいですlt:エンコードするオブジェクトJSON :: XSとJSON :: PPは、未定義のスカラーをJSONヌル値、JSON文字列としてエンコードする前に文字列コンテキストで最後に使用されたスカラー、数値以外のものをエンコードします。

トリックは、エンコードする値をエンコードする直前に数値として「数値化」することです。

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

そして、JSONとJSONの間の文字列としてこれらのメンバーを扱うコードを記述していなければ、データ構造体(例えば '$ data - > {member} + = 0')エンコーディング。技術的に言えば、データを '!SvPOK'にしたいとします。 – hobbs

+0

私は、オブジェクトがmemcacheまたはdbのいずれかから取得されているときに(時には)文字列として扱われていると思います。それは私が変換が起こっている場所を見つけることができる唯一の場所です。 – mark

関連する問題