You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用JSON对象时出现“Modification of a read-only value attempted”错误排查

Perl JSON代码在SLES15 SP7中出现只读值修改错误的原因与解决

问题背景

几年前编写的Perl JSON代码在SLES15 SP6中正常运行,升级到SLES15 SP7后出现以下错误:

Modification of a read-only value attempted at (eval 73)[/usr/lib/perl5/vendor_perl/5.26.1/JSON.pm:287] line 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);

注释最后一行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架构)

JSON.pm中涉事代码片段(第287行为eval $data;):

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

问题原因

  1. 常量的只读特性:Perl中use constant定义的常量属于只读值,即便JSON对象是引用类型,XS后端的实现逻辑会在修改对象属性时触发对常量本身的只读检查。
  2. 后端校验强化:升级后的XS后端(perl-Cpanel-JSON-XS或新增的perl-JSON-XS)对对象属性修改的校验更严格。SP6中使用的PP后端(纯Perl实现)未严格限制这一操作,而XS后端在新版本中强化了只读限制,导致修改常量引用的对象属性时抛出错误。
  3. indent_length的触发逻辑:indent_length的修改逻辑在XS后端中直接关联到常量值的操作,刚好触发了只读检查,而utf8、indent等方法因实现方式不同未触发错误。

解决方法

方案1:替换constant为普通变量

将只读常量改为普通变量,规避只读限制:

use JSON -support_by_pp;
#...
my $JSON_INDENT = JSON->new();
$JSON_INDENT->utf8(1);
$JSON_INDENT->indent(1);
$JSON_INDENT->indent_length(0);

使用时改为:print $JSON_INDENT->pretty->encode($JSON), "\n"

方案2:链式调用初始化对象

创建JSON对象时直接链式调用配置方法,一次性完成属性设置,避免后续修改常量:

use constant JSON_INDENT => JSON->new()->utf8(1)->indent(1)->indent_length(0);

方案3:强制使用PP后端

如果必须保留常量定义,可强制JSON模块使用纯Perl后端,绕过XS的严格检查:

use JSON -support_by_pp;
# 或手动指定后端
$JSON::Backend = 'JSON::PP';

内容的提问来源于stack exchange,提问作者U. Windl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.02 03:47:31