Transformation type perl, javascript, JSON.parse JSON :: XS - need ideas

I am stuck in a problem and I am looking for ideas on the best way to solve it.

I started developing a site where the backend is written in Perl, and the front end makes extensive use of javascript.

The client regularly receives updates from several hundred monitored objects from the backend. Objects are displayed on google map through javascript. An object hash (parsed by javascript) contains a lot of information about the object, for example. location, description, and various state variables.
Some data in string form and some numerical.

The problem is that in the process of pushing data on javascript on the client side, all values ​​become strings. So, in javascript, if I test, for example, to make sure the value is positive, the test succeeds even if the value is 0, because the value is actually "0", not 0.

On the server side, the data is encoded using JSON :: XS as follows:

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 

On the client side, data is decoded using JSON.parse as follows:

 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({}); } } } } 

}

Can anyone see a useful way to solve this? Perl is not strongly typed, and JSON :: XS simply parses numeric data as a string, not a number. I tried adding reviver to JSON.parse (see code below) - however, it does not work (it processes most of the data correctly, but continues to work with various messages, such as non_object_property_call or undefined_method.

Regardless, it would be preferable if the work of analyzing the data to ensure the correct type was handled on the server side. Can anyone see how this can be achieved effectively?

 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; } 

}

+7
source share
1 answer

Simple Perl scalars (any scalar that is not a reference) are the most difficult objects to encode: JSON :: XS and JSON :: PP will encode scanning undefined scalars as NULL JSON values, the rocks that were last used in the string context before encoding as JSON strings, and everything else as a numeric value ...

The trick is to "number" any value that you want to encode as the number on the right before encoding it.

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

All Articles