Perl解码含换行符的JSON文件为何需使用中间变量?
Perl中File::Slurp与decode_json链式调用的坑
问题现象
用Perl处理JSON文件时遇到一个奇怪的情况:
- 将
read_file的结果先存入变量,再传给decode_json,带换行的JSON文件能正常解析; - 直接链式调用
decode_json(read_file('test.json'))时,会抛出JSON解析错误。
示例代码:
use v5.38; use warnings; use strict; use File::Slurp qw( read_file ); use JSON qw( decode_json ); # 正常运行的写法 my $contents = read_file('test.json'); my $decoded = decode_json($contents); say "Decoded contents"; # 报错的写法 my $chained_decoded = decode_json( read_file('test.json') ); say "Decoded chained contents";
测试用带换行的JSON文件内容:
[ { "a": "b" }, { "b": "c" } ]
报错信息:
, or ] expected while parsing array, at character offset 2 (before "(end of string)") at test.pl line 12.
原因解析
核心问题出在Perl的上下文机制,以及File::Slurp的read_file对上下文的响应:
- 当
read_file处于标量上下文(比如赋值给单个变量my $contents = ...)时,它会返回整个文件的内容作为单个字符串,这正是decode_json需要的完整JSON数据。 - 当
read_file处于列表上下文(比如直接作为参数传给decode_json,Perl子程序的参数列表默认是列表上下文)时,它会把文件按行分割,返回每行内容组成的列表。
此时decode_json只会接收列表的第一个元素(也就是JSON的第一行[),用这个不完整的片段解析JSON,自然会触发语法错误。
解决办法
有两种方式可以修复链式调用的问题:
- 强制标量上下文:用
scalar关键字让read_file在标量上下文执行,返回完整字符串:my $chained_decoded = decode_json( scalar read_file('test.json') ); - 保留中间变量:也就是你最初正常运行的写法,通过赋值给标量变量触发标量上下文,这种方式也更直观易读。
内容的提问来源于stack exchange,提问作者awarrier99
相关产品推荐
相关产品推荐

