使用Perl编码复杂的JSON结构

使用Perl编码复杂的JSON结构,json,perl,Json,Perl,我想使用以下代码将MySQL查询的结果编码为JSON字符串。JSON字符串需要如下所示 { "database" : "dbname" "retentionPolicy" : "mytest", "tags" : { "type" : "generate", "location" : "total", "source" : "ehz" }, "points" : [{ "precisi

我想使用以下代码将MySQL查询的结果编码为JSON字符串。JSON字符串需要如下所示

{
    "database" : "dbname"
    "retentionPolicy" : "mytest",
    "tags" : {
        "type" : "generate",
        "location" : "total",
        "source" : "ehz"
    },
    "points" : [{
            "precision" : "ms",
            "timestamp" : "ts1",
            "name" : "power",
            "values" : {
                "value" : "val1"
            }
        }, {
            "precision" : "ms",
            "timestamp" : "ts2",
            "name" : "power",
            "values" : {
                "value" : "val2"
            }
        }, {
            "precision" : "ms",
            "timestamp" : "ts3",
            "name" : "power",
            "values" : {
                "value" : "val3"
            }
        }
    ]
}
带有每个点的
值的
数组
元素让我非常头疼

下面是生成JSON的代码块

my %json_body = (
                'database' => $db_name,
                'retentionPolicy' => $retention,
                'tags' => {
                    'source' => $metric_source,
                    'type' => $metric_type,
                    'location' => $metric_location
                }
                );

# loop through mysql result
while ( ($timestamp, $value) = $query->fetchrow_array() ) {
    my %json_point1 = (
                        'name' => $series_name,
                        'timestamp' => ($timestamp * 1),
                        'precision' => "ms"
                      );
    %json_point2 = ('value' => $value); 
    %json_values = (%json_point1, 'values' => \%json_point2); 
    push(@all_values, \%json_values);       
}
$query->finish();

# Encode json
my %json_data = (%json_body, "points" => \@all_values);
$influx_json = encode_json(\%json_data);
我认为行
push(@all\u值,\%json\u值)
是我的问题。如果我将
%json_data
作为散列引用传递,则只保留
while
循环中的最后一个值。如果我直接使用
%json\u值
,则编码的json会混乱,因为它会丢失结构


任何暗示都将不胜感激。请记住:这个数组和散列引用已经让我头晕目眩了。

我很确定你的问题将是因为你正在使用一个全局范围的散列来表示
%json\u点
%json\u点2
。 你看,这个问题的根源是——你根本没有得到一个散列列表。您将得到一个哈希引用列表

所以这里的问题是——当你把一个对散列的引用推到
@all_值中时,
——你每次推的都是同一个引用。但随后您将覆盖正在引用的哈希的内容

试试这个:

#!/usr/bin/perl

use strict;
use warnings;
use Data::Dumper;

my %hash_thing;
my @all_values; 

for ( 1..3 ) {
   %hash_thing = ( "test" => $_ );
   push ( @all_values, \%hash_thing ) ; 
}

print join ( "\n", @all_values );
print Dumper \@all_values;
你会发现你有三次相同的“值”:

HASH(0x74478c)
HASH(0x74478c)
HASH(0x74478c)
因此,如果您转储它,那么当然-您没有得到正确的数组-因此编码的JSON也无法工作

$VAR1 = [
          {
            'test' => 3
          },
          $VAR1->[0],
          $VAR1->[0]
        ];
最简单的修复方法是使用
my
将散列限定到循环中。(并启用
使用严格;
使用警告(如果没有)

或者,您可以使用如下哈希引用:

my @all_values; 
my $hash_ref;

for ( 1..3 ) {
   $hash_ref =  { "test" => $_ };
   push ( @all_values, $hash_ref ) ; 
}

print @all_values;
print Dumper \@all_values;

由于
$hash\u ref
是一个标量,并且是对匿名哈希的引用,因此可以通过值而不是引用将其插入数组中

您当前使用编码的JSON得到了什么?您的Perl脚本中是否启用了
使用strict
?我认为
%json_point2
%json_值的范围可能会给您带来问题。确保您在while循环中使用了
use strict
,并且您可能希望声明
my%json\u point2
my$json\u值
。@Sobrique和TobyLL我从未想过这一点。你们俩都是对的。非常感谢您为我指出了正确的方向。请务必在您编写的每个Perl源文件的顶部使用strict和warnings。当你还没有自己尝试解决这个问题时,要求免费帮助你的代码是一种冒犯。@Borodin脚本实际上从一开始就使用了严格和警告。我只是在这里复制了脚本中导致问题的部分。即使是你,我也使用了strict,我把变量的范围放错了地方。不过,感谢您指出它的重要性。