2016-08-30 10 views
1

curlから非常に大きなJSONストリーム(数GB)を取得し、jqで処理しようとします。jqで大きなJSONストリームを処理する

私はjqで解析する関連出力は、結果の構造を表す文書にパックされています

{ 
    "results":[ 
    { 
     "columns": ["n"], 

     // get this 
     "data": [  
     {"row": [{"key1": "row1", "key2": "row1"}], "meta": [{"key": "value"}]}, 
     {"row": [{"key1": "row2", "key2": "row2"}], "meta": [{"key": "value"}]} 
     // ... millions of rows  

     ] 
    } 
    ], 
    "errors": [] 
} 

は私がjqrowデータを抽出したいです。これは単純です:

curl XYZ | jq -r -c '.results[0].data[0].row[]' 

結果:curlが完了するまで

{"key1": "row1", "key2": "row1"} 
{"key1": "row2", "key2": "row2"} 

しかし、これは常に待機します。

私はこれに対処するために作られた--streamオプションでプレーしました。私は、次のコマンドを試してみましたが、完全なオブジェクトがcurlから返されるまでも待機している:

curl XYZ | jq -n --stream 'fromstream(1|truncate_stream(inputs)) | .[].data[].row[]' 

dataフィールドに「ジャンプ」に方法はありますし、タグを閉じるのを待たずにrow一つずつ解析を開始しますか?

答えて

2

次のように(1)あなたが使用するバニラフィルタは次のようになります。

jq -r -c '.results[0].data[].row' 

(2)ここでストリーミングパーサーを使用する1つの方法は.results[0].dataの出力を処理するためにそれを使用することですが、おそらく2つのステップの組み合わせはバニラのアプローチよりも遅くなるでしょう。

(3)あなたはこれらの線に沿って何かを試してみたいことがあります。説明の入力については

jq -n --stream 'inputs 
     | select(length==2) 
     | select([.[0][0,2,4]] == ["results", "data", "row"]) 
     | [ .[0][6], .[1]] ' 

(ように変更、それ有効なJSON)、出力は次のようになります。

[ "key", "value1" ] [ "key", "value2" ]

+0

スピードだけではありません。ストリーミングメモリを使用せずに爆発し、curl/jqがクラッシュする。 –

+0

ありがとうございました、あなたのアップデートは本当に助けになりました。すべての行が出力に結合されているので、実際にはそこに到達していません。そして、私は個々の行のすべてのキー/値のペアを収集する方法を理解していません。私はその質問のデータ記述を更新しました。 –

+0

私がしなければならないことは '。[0] [3]'が1つのオブジェクトと等しいすべての配列を組み合わせることだけです。 –

0

は、取得するには:

{"key1": "row1", "key2": "row1"} {"key1": "row2", "key2": "row2"}

から:

{ "results":[ { "columns": ["n"], "data": [
{"row": [{"key1": "row1", "key2": "row1"}], "meta": [{"key": "value"}]}, {"row": [{"key1": "row2", "key2": "row2"}], "meta": [{"key": "value"}]} ] } ], "errors": [] }

jq -c '.results[].data[].row[]'に相当し、以下を行いますが、使用してストリーミング:

​​

何これが行うことは次のとおりです。

  • にJSONを回しストリーム(--stream
  • del(.[0][0:5])付き) "results",0,"data",0,"row"のように、パスのそれらの最初の部分を破棄し
  • select(.[0][0] == "results" and .[0][2] == "data" and .[0][4] == "row"で)パス.results[].data[].row[]を選択し、最後にjq FAQ
  • から fromstream(1|truncate_stream(…))パターンに戻って、予想されるJSONに結果JQストリームを回します

    echo '{"results":[{"columns":["n"],"data":[{"row":[{"key1":"row1","key2":"row1"}],"meta":[{"key":"value"}]},{"row":[{"key1":"row2","key2":"row2"}],"meta":[{"key":"value"}]}]}],"errors":[]}' | jq -cn --stream 'fromstream(1|truncate_stream(inputs | select(.[0][0] == "results" and .[0][2] == "data" and .[0][4] == "row") | del(.[0][0:5])))'

    が生成する:例えば

所望の出力。

関連する問題