如何从perl脚本发送布尔值而不将它们转换为字符串

时间:2017-05-09 10:37:51

标签: json perl boolean

我将Perl数据结构传递给encode_json,并使用其返回的值作为输入发布到restful API。

示例:

$data = (input1 => true);
$json_data = encode_json($data);
print $json_data; // Prints: ["input1":"true"]

$url= http://api.example.com/resources/getDataAPI
$headers = {Accept => 'application/json', Authorization => 'Basic ' . encode_base64($username . ':' . $password)};

$client = REST::Client->new();
$client->POST($url,($json_data,$headers));

这一切都很好。

最近,另一位开发人员进行了很少的输入参数验证检查,REST严格接受布尔值,没有引号。

我现在需要将输入发送为

$data = '["inout1":true]'
$client = REST::Client->new();
$client->POST($url,($data,$headers));

我的所有脚本都失败了,因为输入数据使用encode_json函数编码为JSON格式。

我可以手动形成JSON数据,但输入数据有时非常庞大。无法识别它们并随时修改。

有没有办法可以实现没有引号的传递布尔值?

2 个答案:

答案 0 :(得分:13)

直接在Perl中使用truefalseuse strict下的语法错误,因为 barewords 是不允许的。

我猜您使用的是JSONJSON::XS。那些使用标量引用来表示TRUEFALSE。具体而言,\1\0

$data = ( input1 => \1 );

这是相关的doc from JSON::XS,它允许Types::Serializer::True和Types :: Serializer :: False:

  

来自Types :: Serialiser模块的这些特殊值分别变为JSON true和JSON false值。如果需要,您也可以直接使用\1\0

the doc from JSON,也可以使用JSON::trueJSON::false

  

这些特殊值分别变为JSON true和JSON false值。如果需要,您也可以直接使用\1\0

如果您坚持在true中使用不带引号的my $foo = true,则可以生成返回\1\0的子或常量(实际上是子)。< / p>

use constant false => \0;
sub true () { return \1 } # note the empty prototype

$data = ( input1 => true, input2 => false );

作为Sinan points out in his comment,使用常量会更快,除非你包含一个空原型(子定义中的()),因为这样Perl可以内联调用。

但在我看来,这不仅仅是简单地使用参考文献。总是想想下一个处理这段代码的人。

答案 1 :(得分:1)

simbabque 的答案相反,我真的不认为将引用用作 \1\0 来生成 true 和 {{1 }} 在 JSON 中。

JSON module 中的常量不仅仅是为了方便。

如果您使用这样的常量,您仍然可以在 Perl 中将它们计算为 falsetrue 值,而 false\0 都计算为 {{1} } 在 Perl 中。

并且使用这些常量,除了在 Perl 中保留布尔值之外,还将在 JSON 中工作以生成正确的数据。

这是我所说的一个例子:

\1

该代码将输出如下内容:

true

如您所见,引用 use 5.010; use strict; use warnings; use JSON qw(encode_json decode_json); my $data = { true_1 => JSON::true, true_2 => \1, false_1 => JSON::false, false_2 => \0, }; for my $key (sort keys %$data) { say "$key value is $data->{$key} and is evaluated as true" if $data->{$key}; say "$key value is $data->{$key} and is evaluated as false" if not $data->{$key}; } say encode_json $data; (false_1 value is 0 and is evaluated as false false_2 value is SCALAR(0x146f39b4c18) and is evaluated as true true_1 value is 1 and is evaluated as true true_2 value is SCALAR(0x146f3998918) and is evaluated as true {"true_2":true,"false_1":false,"false_2":false,"true_1":true} ) 的值在 Perl 中被评估为 \0,而设置的值因为 false_2 在 Perl 评估中仍然是 true

另外可以看到,在打印JSON::falsefalse的值时,它们会自动转换为JSON::trueJSON::false,而10 被打印为 \1\0

最后,当转换为 SCALAR(0x146f3998918) 时,两者都可以正常工作。但是在 Perl 数据结构中设置应该为假的“真”值(SCALAR(0x146f39b4c18),空字符串或 JSON),可能会导致代码的其他部分出现错误,您可能会在这些部分使用相同的结构和评估布尔字段来做某事。

此外,在开发级别,与将引用视为 0 和 {{1 }} 并且如果他/她不熟悉这种技巧,则无法理解引用的原因。

如果您真的想避免输入那些额外的 6 个字符,那么您可以在代码顶部执行此操作:

undef

然后您可以简单地将它们用作代码中的常量,如下所示:

JSON::true

虽然,也许常量名称应该全部大写(如 JSON::false\1),但这是一个不同的讨论主题。

因此,在使用 Perl 和 JSON 时,请始终使用 \0use JSON qw(encode_json decode_json); sub true () { JSON::true } sub false () { JSON::false } 。它们将在 Perl 中得到很好的评估,它们在 JSON 中被转换为正确的数据类型,并且它们可以正确地打印到控制台和文件。 $data = { is_member => true, is_suspended => false, } 也是如此。