2014-11-08 69 views
3

我想JSON:XS在一行上輸出數組元素。例如:格式陣列的JSON輸出

use warnings; 
use strict; 
use JSON::XS; 

my $h={a=>[1,2,3,4],b=>3}; 
my $coder = JSON::XS->new->pretty; 
my $txt = $coder->encode($h); 
print $txt; 

這給出輸出:

{ 
    "b" : 3, 
    "a" : [ 
     1, 
     2, 
     3, 
     4 
    ] 
} 

而我的期望的輸出是:

{ 
    "b" : 3, 
    "a" : [ 1, 2, 3, 4 ] 
} 

回答

2

此行爲在模塊中硬編碼。如果您沒有問題修補您電腦上的模塊代碼就可以輕鬆完成(以下說明是針對Linux的CPAN):

  1. 轉至CPAN build目錄/root/.cpan/build/JSON-XS-3.01-*(實際名稱具有在年底一些隨機字符)
  2. 應用下面的補丁XS.xs
--- XS.xs.orig 2014-11-08 14:22:37.682348401 +0300 
+++ XS.xs  2014-11-08 14:30:01.447643990 +0300 
@@ -486,6 +486,15 @@ 
    encode_space (enc); 
} 

+INLINE void 
+encode_comma_singleline (enc_t *enc) 
+{ 
+ encode_ch (enc, ','); 
+ 
+ if (enc->json.flags & F_SPACE_AFTER) 
+ encode_space (enc); 
+} 
+ 
static void encode_sv (enc_t *enc, SV *sv); 

static void 
@@ -500,24 +509,18 @@ 

    if (len >= 0) 
    { 
-  encode_nl (enc); ++enc->indent; 
- 
     for (i = 0; i <= len; ++i) 
     { 
      SV **svp = av_fetch (av, i, 0); 

-   encode_indent (enc); 
- 
      if (svp) 
      encode_sv (enc, *svp); 
      else 
      encode_str (enc, "null", 4, 0); 

      if (i < len) 
-   encode_comma (enc); 
+   encode_comma_singleline (enc); 
     } 
- 
-  encode_nl (enc); --enc->indent; encode_indent (enc); 
    } 

    encode_ch (enc, ']'); 
  • 運行make,然後make install

  • 檢查你的腳本:

  • $ perl json.pl 
    { 
        "a" : [1, 2, 3, 4], 
        "b" : 3 
    } 
    

    一些必要的聲明:接受你自己的風險局部地改變模塊,當然正確的做法是有一個良好的補丁,它會接受相應的配置選項,並將該補丁提交給模塊的作者。但是,如果您只需要在計算機上運行它,那就完美了。

    +0

    謝謝!這看起來不錯,但我找不到'XS.xs'文件。其他人(在其他機器上)也會使用這個程序,所以我認爲這不是一個在本地修改源代碼的選項。最好是提交給我認爲模塊作者的補丁。不管怎麼說,還是要謝謝你! – 2014-11-08 12:03:18

    +0

    您是從CPAN手動安裝軟件包還是使用軟件包管理器?如果你是從軟件包安裝的,刪除它('rpm -e perl-JSON-XS'或類似的東西,取決於你的系統),然後用CPAN安裝:'perl -MCPAN -e'install JSON :: XS'' 。您將擁有一個帶有模塊源代碼的「build」目錄,包括'XS.xs'。 – afenster 2014-11-08 12:06:06

    +0

    或者用這個補丁重建RPM也許更好。取決於你喜歡哪種方法。 – afenster 2014-11-08 12:06:31

    0

    如果陣列不能包含哈希,以下可能是解決方法:

    use warnings; 
    use strict; 
    use JSON::XS; 
    use Text::Balanced qw(extract_bracketed extract_delimited); 
    use Text::CSV; 
    my $csv = Text::CSV->new({ sep_char => ',', allow_whitespace => 1 }); 
    
    my $h = { a => "[", g => [ "[", 2, "bb]]", 4 ], b => 3, c => [ 1, 2, 3, 4 ] }; 
    my $coder = JSON::XS->new->pretty; 
    my $txt = $coder->encode($h); 
    my $str = ""; 
    while (1) { 
        my $ind1 = index($txt, '"'); 
        my $ind2 = index($txt, '['); 
        if ($ind1 >= 0 && $ind2 >= 0) { 
         if ($ind1 < $ind2) { 
          skipQuoted(\$txt, \$str); 
          next; 
         } 
        } 
        elsif ($ind2 < 0) { 
         $str .= $txt; 
         last; 
        } 
        my ($etxt, $end, $beg) = extract_bracketed($txt, '["]', '[^[]*'); 
        die "Unexpected!" if !defined $etxt; 
        $str .= $beg; 
        $etxt = substr($etxt, 1, length($etxt) - 2) 
         ; #strip leading and trailing brackets 
        $etxt =~ s{\n}{}g; 
        my @elem; 
        if ($csv->parse($etxt)) { 
         @elem = $csv->fields(); 
        } 
        else { 
         die "Unexpected!"; 
        } 
        $str .= '[ ' . processFields(\@elem) . ' ]'; 
        $txt = $end; 
    } 
    
    print $str; 
    
    sub skipQuoted { 
        my ($txt, $str) = @_; 
    
        my ($s1, $s2, $s3) = extract_delimited($$txt, '"', '[^"]*'); 
        die "Unexpected!" if !defined $s1; 
        $$str .= $s3 . $s1; 
        $$txt = $s2; 
    } 
    
    sub processFields { 
        my ($a) = @_; 
    
        for (@$a) { 
         if ($_ !~ /^-?(0|([1-9][0-9]*))(\.[0-9]+)?([eE][-+]?[0-9]+)?$/) { 
          $_ = '"' . $_ . '"'; 
         } 
        } 
        return join(", ", @$a); 
    } 
    

    輸出:

    { 
        "a" : "[", 
        "g" : [ "[", 2, "bb]]", 4 ], 
        "b" : 3, 
        "c" : [ 1, 2, 3, 4 ] 
    }