Perl、JSON、浮点数、引号
Perl, JSON, float, quotes
我们有一个 Perl 应用程序,它根据数据库查询创建 JSONs。不幸的是,它错误地处理了浮点数,因为它在浮点数周围加上了双引号。
例如:
use DBI;
use JSON::MaybeXS;
my $dbs="dbi:ODBC:myconnection,myuser,mypwd,";
my @ARR=split/,/ ,$dbs;
$dbh = DBI->connect(@ARR, { PrintError=>0, RaiseError=>1, LongReadLen=>60000}) ;
my $sql = "SELECT 'Hello there' str, '0.0123' str_flt, 0.0123 flt_sm, 10.1234 flt_lg, 1234 nt, getdate() dt";
my $sth = $dbh->prepare($sql);
$sth->execute();
my $rows = $sth->fetchall_arrayref({});
print "Structure of result is: \n\n";
my $num_fields = $sth->{NUM_OF_FIELDS};
for ( my $i=0; $i< $num_fields; $i++ ) {
my $field = $sth->{NAME}->[$i];
my $type = $sth->{TYPE}->[$i];
my $precision = $sth->{PRECISION}->[$i]; # e.g. VARCHAR(50) has a precision of 50
print "Field $field is of type $type, with precision $ precision\n";
}
$sth->finish();
$dbh->disconnect;
my $json_opts = JSON::MaybeXS->new(utf8 => 1, pretty => 1);
my $json_maybe = $json_opts->encode($rows);
print("\nJSON::MaybeXS:\n");
print($json_maybe);
输出如下:
Structure of result is:
Field str is of type -8, with precision 11
Field str_flt is of type -8, with precision 6
Field flt_sm is of type 2, with precision 4
Field flt_lg is of type 2, with precision 6
Field nt is of type 4, with precision 10
Field dt is of type 93, with precision 23
JSON::MaybeXS:
[
{
"dt" : "2018-10-05 09:42:43.483",
"nt" : 1234,
"flt_sm" : ".0123",
"str" : "Hello there",
"str_flt" : "0.0123",
"flt_lg" : "10.1234"
}
]
Perl 版本:5.18.2
已安装 JSON 库:JSON、JSON-Any、JSON-PP、JSON-XS、Cpanel-JSON -XS,JSON-MaybeXS,Parse-CPAN-Meta
有一件事,输出打乱了字段,每个 运行 导致 JSON 中的顺序不同。主要问题是浮点数周围的双引号,这会导致在另一个应用程序中使用它时出现问题,因为它将这些字段识别为字符串并且必须一个一个地解析它们。 DBI 正确识别字段类型,它在 json 编码期间以某种方式丢失了......知道如何解决它吗? (是的,我可以使用正则表达式轻松修复它,但那不是很好...)
这就是 Cpanel::JSON::XS has Cpanel::JSON::XS::Type 的原因。请注意,浮点数可能会丢失精度。
#!/usr/bin/perl
use warnings;
use strict;
use Cpanel::JSON::XS;
use Cpanel::JSON::XS::Type;
my $type = json_type_arrayof({
dt => JSON_TYPE_STRING,
nt => JSON_TYPE_INT,
flt_sm => JSON_TYPE_FLOAT,
str => JSON_TYPE_STRING,
str_flt => JSON_TYPE_FLOAT,
flt_lg => JSON_TYPE_FLOAT,
});
my $data = [{
dt => "2018-10-05 09:42:43.483",
nt => 1234,
flt_sm => ".0123",
str => "Hello there",
str_flt => "0.0123",
flt_lg => "10.1234",
}];
my $jsonizer = Cpanel::JSON::XS->new->canonical->pretty;
print $jsonizer->encode($data, $type);
尝试这样的操作,通过添加 0 将您的数字字段转换为数字。类似的方法对我有用过一次。使用 JSON::XS 版本 3.02.
use JSON::XS 3.02;
...
my @numfield=qw( nt flt_sm str_flt flt_lg );
for my $f (@numfield) {
defined $$_{$f} and $$_{$f}+=0 for @$rows;
}
...
我们有一个 Perl 应用程序,它根据数据库查询创建 JSONs。不幸的是,它错误地处理了浮点数,因为它在浮点数周围加上了双引号。
例如:
use DBI;
use JSON::MaybeXS;
my $dbs="dbi:ODBC:myconnection,myuser,mypwd,";
my @ARR=split/,/ ,$dbs;
$dbh = DBI->connect(@ARR, { PrintError=>0, RaiseError=>1, LongReadLen=>60000}) ;
my $sql = "SELECT 'Hello there' str, '0.0123' str_flt, 0.0123 flt_sm, 10.1234 flt_lg, 1234 nt, getdate() dt";
my $sth = $dbh->prepare($sql);
$sth->execute();
my $rows = $sth->fetchall_arrayref({});
print "Structure of result is: \n\n";
my $num_fields = $sth->{NUM_OF_FIELDS};
for ( my $i=0; $i< $num_fields; $i++ ) {
my $field = $sth->{NAME}->[$i];
my $type = $sth->{TYPE}->[$i];
my $precision = $sth->{PRECISION}->[$i]; # e.g. VARCHAR(50) has a precision of 50
print "Field $field is of type $type, with precision $ precision\n";
}
$sth->finish();
$dbh->disconnect;
my $json_opts = JSON::MaybeXS->new(utf8 => 1, pretty => 1);
my $json_maybe = $json_opts->encode($rows);
print("\nJSON::MaybeXS:\n");
print($json_maybe);
输出如下:
Structure of result is:
Field str is of type -8, with precision 11
Field str_flt is of type -8, with precision 6
Field flt_sm is of type 2, with precision 4
Field flt_lg is of type 2, with precision 6
Field nt is of type 4, with precision 10
Field dt is of type 93, with precision 23
JSON::MaybeXS:
[
{
"dt" : "2018-10-05 09:42:43.483",
"nt" : 1234,
"flt_sm" : ".0123",
"str" : "Hello there",
"str_flt" : "0.0123",
"flt_lg" : "10.1234"
}
]
Perl 版本:5.18.2
已安装 JSON 库:JSON、JSON-Any、JSON-PP、JSON-XS、Cpanel-JSON -XS,JSON-MaybeXS,Parse-CPAN-Meta
有一件事,输出打乱了字段,每个 运行 导致 JSON 中的顺序不同。主要问题是浮点数周围的双引号,这会导致在另一个应用程序中使用它时出现问题,因为它将这些字段识别为字符串并且必须一个一个地解析它们。 DBI 正确识别字段类型,它在 json 编码期间以某种方式丢失了......知道如何解决它吗? (是的,我可以使用正则表达式轻松修复它,但那不是很好...)
这就是 Cpanel::JSON::XS has Cpanel::JSON::XS::Type 的原因。请注意,浮点数可能会丢失精度。
#!/usr/bin/perl
use warnings;
use strict;
use Cpanel::JSON::XS;
use Cpanel::JSON::XS::Type;
my $type = json_type_arrayof({
dt => JSON_TYPE_STRING,
nt => JSON_TYPE_INT,
flt_sm => JSON_TYPE_FLOAT,
str => JSON_TYPE_STRING,
str_flt => JSON_TYPE_FLOAT,
flt_lg => JSON_TYPE_FLOAT,
});
my $data = [{
dt => "2018-10-05 09:42:43.483",
nt => 1234,
flt_sm => ".0123",
str => "Hello there",
str_flt => "0.0123",
flt_lg => "10.1234",
}];
my $jsonizer = Cpanel::JSON::XS->new->canonical->pretty;
print $jsonizer->encode($data, $type);
尝试这样的操作,通过添加 0 将您的数字字段转换为数字。类似的方法对我有用过一次。使用 JSON::XS 版本 3.02.
use JSON::XS 3.02;
...
my @numfield=qw( nt flt_sm str_flt flt_lg );
for my $f (@numfield) {
defined $$_{$f} and $$_{$f}+=0 for @$rows;
}
...