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

Perl v5.36.0调用S3分片API时PartNumber转字符串问题求助

问题背景

使用Perl v5.36.0脚本调用AWS S3分片上传API,完成分片上传后,Data::Dumper输出的哈希中PartNumber为整数类型,但通过encode_json将哈希序列化为JSON并写入文件后,所有PartNumber被转为字符串,导致complete-multipart-upload API调用失败,错误提示参数类型不匹配(要求整数,实际为字符串)。

相关代码片段

分片上传并构建Part信息的代码:

my $part_no = 1;
my %final_upload_file;
my @multi_part_hash;

foreach my $temp_file (@split_files) {
   my $tota_no_parts= @split_files;
   my $upload_part = "aws s3api upload-part --bucket <s3_bucket_name> --key ".$filename." --part-number ".$part_no." --body ".$temp_file." --upload-id ".$UploadId;
   $temp_json=`$upload_part`;
   
   my %upload_response = %{decode_json $temp_json};

   my $eTag = $upload_response{'ETag'};
   my %temp_part_hash;
   $temp_part_hash{'PartNumber'} = int($part_no);
   $temp_part_hash{'ETag'} = $eTag;
   push @multi_part_hash, \%temp_part_hash;

    if( $part_no le $tota_no_parts)
    {
     $part_no++;
    }
}
my %final_hash;
$final_hash{'Parts'} = \@multi_part_hash;
print Dumper(\%final_hash);

序列化JSON的代码:

my $json_text = encode_json \%final_hash;
print("\$json_text: $json_text\n");
my $json_filename = 'test.json';
 open(FH, '>', $json_filename) or die $!;
 print FH $json_text;
 close(FH);

使用的模块:

use strict;
use FileHandle;
use Getopt::Long;
use POSIX;
use Data::Dumper;
use feature q(say);
use JSON;

现象与错误

  • Data::Dumper输出的PartNumber为整数:

$VAR1 = {
'Parts' => [
{
'PartNumber' => 1,
'ETag' => '"46f438ba2afd8d6dc03958b867a349b1"'
},
...(其余分片信息)
]
};

  • 序列化后的JSON中PartNumber为字符串:

$json_text:
{"Parts":[{"PartNumber":"1","ETag":""46f438ba2afd8d6dc03958b867a349b1""},{"ETag":""7b1e03e9ed7bb49d907e5a2d25b89159""},{"PartNumber":"2"},...]}

  • API调用错误信息:

Parameter validation failed: Invalid type for parameter
MultipartUpload.Parts[0].PartNumber, value: 1, type: <class 'str'>,
valid types: <class 'int'>
...(其余分片的相同错误)

修复方案

问题根源是Perl弱类型特性导致JSON模块序列化时无法准确识别数字类型,以下是几种可靠的修复方式:

1. 替换为JSON::XS模块

JSON::XS是更严谨的JSON序列化模块,对Perl变量的类型识别更准确,能确保整数被序列化为JSON数字类型:

# 替换原有的use JSON;为
use JSON::XS;

# 序列化代码无需修改
my $json_text = encode_json \%final_hash;

2. 启用核心JSON模块的convert_blessed选项

如果坚持使用Perl核心的JSON模块,可以通过启用convert_blessed选项来优化类型识别:

use JSON;

# 创建JSON对象并启用选项
my $json_serializer = JSON->new->convert_blessed;
my $json_text = $json_serializer->encode(\%final_hash);

3. 强制将PartNumber转为数字类型

Perl中可以通过数字上下文强制变量转为数字类型,确保内部标记为数字,让JSON模块正确序列化:

# 在构建Part信息时,将int($part_no)替换为0+$part_no
$temp_part_hash{'PartNumber'} = 0 + $part_no;

0+$part_no会强制变量进入数字上下文,将其内部类型标记为数字,序列化时就会输出为无引号的JSON数字。


内容的提问来源于stack exchange,提问作者Rito Sarkar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 07:55:59