2013-05-31 164 views
1

請問有沒有辦法讓encode_json方法不要在數字中加引號?如何避免用Perl JSON模塊引用數字引號?

比如我使用的是在CentOS 6.3的Perl 5.10(也是ActiveState的Perl的5.16在Win 7),它把引號,它應該不會:

# perl -MJSON -e 'print encode_json({a => [split(",", "1.2,30")]});' 
{"a":["1.2","30"]} 

也就是說,確定是的,它在上面的代碼中看到「1.2」和「30」爲字符串,但我的問題是:

我的perl腳本解析CSV文件並生成HTML文件using Google Charts而後者通過引用數字值引起混淆(儘管我告訴他們該列是「數字」類型的)。

作爲一種變通方法我通過我的數據意象結構迭代和sprintf "%f", $val更換每一個數字,但這會導致過多的空值的每個數字,這使得圖表無誤後進行顯示,但是難看:

# perl -e 'printf "%f", "30"' 
30.000000 

enter image description here

UPDATE:

是,添零或一個乘以似乎工作第一眼:

# perl -MJSON -e 'print encode_json({a => [map {1 * $_} split(",", "1.2,30")]});' 
{"a":[1.2,30]} 

my real script它仍然爲浮點數不起作用。

而且你可以看到這個問題用自卸車模塊太當我還是在CLI:

# perl -MData::Dumper -e 'print Dumper({a => [map {1.0 * $_} split(",", "1.2,30")]});' 
$VAR1 = { 
      'a' => [ 
        '1.2', # <= THIS IS MY PROBLEM AND CONFUSES GOOGLE CHARTS 
        30 
       ] 
     }; 
+0

自卸車總是添加引號浮點數,所以這是完全沒有意義的。 – ikegami

+0

如果該代碼有效,而不是您的「真實腳本」,這是因爲您在「真實腳本」中做了一些不同的事情! – ikegami

+0

我在http://pastebin.com/3sn6yPaD上的真實腳本除了在CSV行上調用'split'然後調用'encode_json'外幾乎沒有什麼作用。而後者在浮點值附加引號,並沒有解決方法幫助那裏。 –

回答

6

他們出來爲字符串,因爲你得到串出split

有可能是做一個更好的方式,而是通過1只乘以出現他們的工作:

perl -MJSON -e 'print encode_json({a => [map { $_ * 1 } split(",", "1.2,30")]});' 
+0

不幸的是,由於某些原因,這不適用於浮動數字。我也試過'+ 0.0'和'* 1.0' –

+0

我得到了'{「a」:[1.2,30]}作爲輸出,所以它對我來說是浮動數字。也許你有一箇舊版本的JSON模塊? – Quentin

+0

不,但謝謝大家的幫助。我會進一步調查,也許去尋求JavaScript解決方案:https://groups.google.com/forum/#!topic/google-visualization-api/EUXBop_HQ5M –

3

的Perl跟蹤標量數據類型的內部。您可以通過在算術表達式中使用它來強制標量的類型爲數字。例如:

sprintf "%.2f", $val 

my $scalar = "3.14"; # $scalar is a string 
$scalar *= 1;  # Now $scalar is a number 

在另一方面,如果你的問題是具有在sprintf輸出太多的零,你可以通過改變精確到別的東西,例如2位修復

+1

或'sprintf'%g「,...'讓Perl擔心要顯示多少位數 – mob

8

你的問題是,雖然你正確地將它轉換爲數字,但在你調用encode_json之前它已經轉換回字符串。這是因爲你在調試語句中調用了Data :: Dumper。如果您將您對Data :: Dumper的調用註釋掉,您會發現encode_json輸出正確的東西。

例如這個例子說明之前並調用翻斗車在物體上後,JSON對象:

$ perl -MData::Dumper -MJSON -e ' 
my $obj = {a => [map { $_ - 0 } split(",", "1.2,30")]}; 
print "JSON before: ",encode_json($obj),"\n"; 
print "Dumper: ",Dumper($obj); 
print "JSON after: ",encode_json($obj),"\n"; 
' 
JSON before: {"a":[1.2,30]} 
Dumper: $VAR1 = { 
      'a' => [ 
        '1.2', 
        30 
       ] 
     }; 
JSON after: {"a":["1.2",30]} 

,你可以看到,自卸車實際修改你傾倒的對象,影響你以後的encode_json電話。

+1

謝謝。自卸車也是我的問題。我從來沒有懷疑過據稱只讀操作正在修改它的輸入。 – Kyle

+1

我有完全相同的問題......我也震驚Data :: Dumper正在修改它的參數! – davidreedernst

9

你已經有了這個答案,但我想指出在Perl中這樣做的慣用方式。從chapter 10 of Modern Perl

要確保Perl將值作爲數字,加零:

my $numeric_value = 0 + $value; 

要確保Perl將值作爲布爾,雙否定它:

my $boolean_value = !! $value; 

爲確保Perl將值視爲字符串,請將其與空字符串連接起來:

my $string_value = '' . $value; 
+0

我只是想在這裏留言,因爲我在這個實現中遇到了很多麻煩。如果您將0或乘以1以將您的字符串轉換爲數字值,然後使用JSON編碼,請使用最新版本的JSON :: XS。在某些情況下,您可以使用此技巧,並且JSON編碼仍然會導致顯示字符串。 – user3333134

0

正確解決方案已經給出。

如果出於任何原因,你覺得難以採納,這裏是一個更容易的建議,感謝Data::Dump它做了所有爲我們的辛勤工作:

perl -MJSON -MData::Dump=pp -le 'print encode_json eval pp { a => [split /,/, "1.2,30,b"] }' 

這給:

{"a":[1.2,30,"b"]} 

如果您的效率限制允許承擔往返,它應該幾乎透明地解決您的問題。

它也可以指出您在測試中獲得的報價實數只是因爲其他人已經提到的Data::Dumper(可疑)選項。

+0

我在http://pastebin.com/3sn6yPaD的真實腳本不使用Data :: Dumper來生成字符串。 –

+0

我指的是原始文章底部顯示的測試,在使用'Data :: Dumper'轉換你的數據結構(我將* Data :: Dumper'指責爲*可疑選項*引用雷亞爾)。 無論如何,你的腳本可以在encode_json之前使用'pp' /'eval'(如我的單行程所示),你的問題應該會消失。 – emazep

1

我有一個類似的情況。我的perl代碼生成(以複雜的方式)一個複雜的數據結構,然後用JSON :: to_json序列化並傳遞給javascript。數據結構中有許多不同深度的數字,並且JavaScript會對它們進行算術運算。

javascript中的'+'用作數字的加法和字符串的連接,因此在將數字轉換爲json時不要將數字放在引號中非常重要。另一方面,數據是相當複雜的,所以我需要簡單和通用的方式來強制數字是任意數組/散列/散列數組中的數字。

所以,我結束了這樣的功能:

use Scalar::Util qw(looks_like_number); 
sub force_numbers 
{ 
    if (ref $_[0] eq ""){ 
     if (looks_like_number($_[0])){ 
      $_[0] += 0; 
     } 
    } elsif (ref $_[0] eq 'ARRAY'){ 
     force_numbers($_) for @{$_[0]}; 
    } elsif (ref $_[0] eq 'HASH') { 
     force_numbers($_) for values %{$_[0]}; 
    } 

    return $_[0]; 
} 

現在我可以將數據轉換爲JSON之前使用它:

print to_json(force_numbers($data));