如何在Perl中解析复杂JSON并提取嵌套数组指定字段
问题背景
- 待解析的多层嵌套JSON存储在变量
$keycloak_response中,使用Perl的JSON模块(引入方式:use JSON qw( decode_json );)完成解析 - JSON结构包含page分页信息、
networkelements网元数组:单个网元条目下包含name、networkAddresses等属性,其中networkAddresses是存储IP地址、端口信息的子数组 - 需求:提取
networkelements数组中每个网元的name字段值,以及对应网元下networkAddresses数组内每个条目的address(IP地址)、port(端口)字段值,逐行输出逗号分隔内容,预期共输出3行记录,现有代码无法得到预期结果
可直接运行的正确实现代码
use strict; use warnings; use JSON qw( decode_json ); use utf8; # 设置标准输出编码,避免中文等非ASCII字符乱码 binmode(STDOUT, ":encoding(UTF-8)"); # 解码JSON字符串为Perl嵌套结构 my $parsed = decode_json($keycloak_response); # 校验顶层networkelements数组存在且为数组类型,避免结构异常报错 if (exists $parsed->{networkelements} && ref $parsed->{networkelements} eq 'ARRAY') { # 遍历每一个网元条目 for my $ne_item (@{$parsed->{networkelements}}) { my $ne_name = $ne_item->{name} // ''; # 跳过不存在networkAddresses数组的异常网元条目 next unless exists $ne_item->{networkAddresses} && ref $ne_item->{networkAddresses} eq 'ARRAY'; # 遍历当前网元下的每一个地址端口条目 for my $addr_item (@{$ne_item->{networkAddresses}}) { my $ip = $addr_item->{address} // ''; my $port = $addr_item->{port} // ''; # 逗号分隔逐行输出 print join(',', $ne_name, $ip, $port) . "\n"; } } }
常见报错&结果不符合预期的排查点
- 数组引用未正确解引用:Perl中
decode_json输出的数组、哈希都是引用类型,遍历数组必须用@{$引用变量}的格式解引用,直接遍历引用本身不会拿到数组元素 - 字段层级访问错误:
networkAddresses是networkelements数组子项的属性,不是JSON顶层字段,不要跳过网元层级直接访问 - 字段名拼写/大小写错误:JSON字段名大小写敏感,注意
networkAddresses是复数结尾,不要漏写末尾的s - 结构认知偏差:如果输出行数不对,可以临时引入Data::Dumper模块打印解析后的完整结构,核对实际层级:
use Data::Dumper; print Dumper($parsed); - 未做缺省值处理:如果部分条目缺失
name/address/port字段,直接访问会触发未初始化值警告,用//操作符给缺省字段赋值空串即可避免
内容的提问来源于stack exchange,提问作者Many
相关产品推荐
相关产品推荐

