在使用JSON对象时,试图修改只读值
几年前我用JSON写过一些Perl代码。它在SLES15 SP6仍然可以工作,但在SLES15 SP7时我得到了如下错误:
尝试修改只读值时发生错误,出现在 (eval 73)[/usr/lib/perl5/vendor_perl/5.26.1/JSON.pm:287] 第63行。
相关的代码是:
use JSON -support_by_pp;
#...
use constant JSON_INDENT => JSON->new(); # indenting JSONizer
JSON_INDENT->utf8(1);
JSON_INDENT->indent(1);
JSON_INDENT->indent_length(0);
如果我把最后一行注释掉,错误就不会再发生。
(我在代码中像 print JSON_INDENT->pretty->encode($JSON), "\n" 那样使用常量)
在SP升级时,我注意到了这些相关的变动:
添加了软件包 perl-JSON-XS-4.40.0-bp157.2.3.1.x86_64,并且将软件包 perl-Cpanel-JSON-XS 从 4.37-bp156.2.3.1 升级到了 4.380.0-150700.3.3.1(两者都是 x86_64)。
问题出在哪里,应该如何解决?
相关的软件包代码是:
sub _load_xs {
my ($module, $opt) = @_;
__load_xs($module, $opt) or return;
my $data = join("", <DATA>); # this code is from Jcode 2.xx.
close(DATA);
eval $data;
JSON::Backend::XS->init($module);
return 1;
};
第287行是 eval $data;。
解决方案
如果你要定义一个常量,正如你在关于它的无数问题中已经注意到的那样,这是一种容易出错的做法,请一次性创建对象并设置它的所有状态:
BEGIN { $ENV{PERL_JSON_BACKEND} = 'JSON::PP' }
use JSON;
use constant JSON_INDENT => do {
JSON->new->utf8(1)->indent(1)->indent_length(0);
};
say JSON_INDENT->encode($hash);
不过,这也可以改成一个子例程(这正是 constant 为你所做的)。这实际上更像一个常量,因为你没有办法修改这个对象:
say JSON_INDENT($hash);
sub JSON_INDENT {
state $json = JSON->new->utf8(1)->indent(1)->indent_length(0);
$json->encode(@_);
}
但你不需要调用子例程就能直接达到你想要的结果:
my $JSON_INDENT = JSON->new->utf8(1)->indent(1)->indent_length(0);
say $JSON_INDENT->encode($hash);
请选择不会引发问题的那个方案,而不是你选择的那个。
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。