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

Perl脚本转换JSON到CSV仅生成表头无数据问题排查

Perl脚本转换JSON到CSV无数据输出的问题分析与解决

问题场景

尝试用Perl脚本将out_spot.json转换为CSV格式,期望输出两个表格:一个存储spotterId、spotterName等设备基础信息,另一个存储track数组中的轨迹坐标与时间信息。但脚本运行无报错,生成的CSV仅包含表头,无任何数据行。

用户原脚本代码

use strict;
use warnings;
use Text::CSV_XS;
use JSON::MaybeXS;
use FileHandle ;
use IO::Handle;

local( $/, *FH ) ;

open( FH, '<', 'out_spot.json' ) or die "Can't open out_spot.json: $!";
my $text = <FH>;

my $data = decode_json($text);

my $csv = Text::CSV_XS->new({auto_diag=>2,binary=>1, eol=>"\n", always_quote=>1 });

open(my $OUT, ">>:encoding(utf8)", "out_spot.csv") or die "out_spot.csv: $!";
my @fields = qw/    spotterId   spotterName payloadType batteryVoltage  batteryPower    solarVoltage    humidity    track   latitude    longitude   timestamp   waves   significantWaveHeight   peakPeriod  meanPeriod  peakDirection   peakDirectionalSpread   meanDirection   meanDirectionalSpread   timestamp   latitude    longitude   frequencyData   frequency   df  varianceDensity direction   directionalSpread   timestamp   latitude    longitude /;
$csv->print($OUT, \@fields);
for my $datapoint ( @{ $data->{data} } ) {
   $csv->print($OUT, [ map {$datapoint->{$_}} @fields ]);
}

close $OUT;

对应的JSON结构示例

{
   "data" : {
       "spotterId" : "SPOT-30344R",
       "spotterName" : "",
       "payloadType" : "full",
       "batteryVoltage" : 4.01,
       "batteryPower" : -0.15,
       "solarVoltage" : 0.22,
       "humidity" : 46.4,
       "track" : [{
           "latitude" : -28.4223833,
           "longitude" : -37.5605,
           "timestamp" : "2023-09-12T06:28:31.000Z"
       }, {
           "latitude" : -28.4279833,
           "longitude" : -37.56795,
           "timestamp" : "2023-09-12T06:58:31.000Z"
       }],
    .....
}

问题根源

  1. 数据结构访问错误:JSON中的data是一个哈希对象(而非数组),但脚本中用@{ $data->{data} }尝试将其作为数组遍历,这会导致循环体完全不执行——哈希无法被强制转为数组,自然不会输出任何数据行。
  2. 表头设计混乱:原表头将基础信息、轨迹字段、其他嵌套字段全部混在一起,既不符合“两个独立表格”的需求,也无法正确提取嵌套数组中的数据。
  3. 嵌套数组未处理:track是包含多条轨迹的数组,原代码直接取$datapoint->{track}只会输出数组的字符串化结果,无法提取每条轨迹的具体坐标与时间。

修正后的解决方案

以下脚本会生成两个独立的CSV文件:spot_basic_info.csv存储设备基础信息,spot_track.csv存储轨迹数据:

use strict;
use warnings;
use Text::CSV_XS;
use JSON::MaybeXS;

# 读取并解析JSON文件
open(my $fh, '<', 'out_spot.json') or die "无法打开out_spot.json: $!";
local $/;
my $json_text = <$fh>;
close $fh;
my $data = decode_json($json_text);
my $spot_data = $data->{data};

# 初始化CSV对象
my $csv = Text::CSV_XS->new({
    auto_diag   => 2,
    binary      => 1,
    eol         => "\n",
    always_quote=> 1
});

# 生成基础信息CSV
open(my $basic_out, '>:encoding(utf8)', 'spot_basic_info.csv') or die "无法创建spot_basic_info.csv: $!";
my @basic_fields = qw/spotterId spotterName payloadType batteryVoltage batteryPower solarVoltage humidity/;
$csv->print($basic_out, \@basic_fields);
# 基础信息只有一行,直接输出
$csv->print($basic_out, [ map { $spot_data->{$_} } @basic_fields ]);
close $basic_out;

# 生成轨迹信息CSV
open(my $track_out, '>:encoding(utf8)', 'spot_track.csv') or die "无法创建spot_track.csv: $!";
my @track_fields = qw/latitude longitude timestamp/;
$csv->print($track_out, \@track_fields);
# 遍历track数组输出每条轨迹
for my $track_point (@{ $spot_data->{track} }) {
    $csv->print($track_out, [ map { $track_point->{$_} } @track_fields ]);
}
close $track_out;

修正要点说明

  • 正确访问data哈希对象,直接提取其中的基础信息字段
  • 单独处理track数组,遍历每条轨迹数据生成独立行
  • 拆分输出为两个CSV文件,分别对应需求中的两个表格
  • 移除了冗余的FileHandle和IO::Handle模块,简化代码

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 23:05:17