亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何使用jq將任意簡單的JSON轉換為CSV?

如何使用jq將任意簡單的JSON轉換為CSV?

大話西游666 2019-11-25 10:51:42
使用jq,如何將淺層對象數組的任意JSON編碼轉換為CSV?這個站點上有很多問答,涵蓋了對字段進行硬編碼的特定數據模型,但是對于任何JSON,此問題的答案都應該有效,唯一的限制是它是具有標量屬性的對象數組(無深度/復雜/子對象,如將它們展平是另一個問題)。結果應該包含一個標題行,給出字段名稱。將優先選擇保留第一個對象的字段順序的答案,但這不是必須的。結果可以用雙引號將所有單元格括起來,或者只將需要引用的單元格括起來(例如“ a,b”)。例子輸入:[    {"code": "NSW", "name": "New South Wales", "level":"state", "country": "AU"},    {"code": "AB", "name": "Alberta", "level":"province", "country": "CA"},    {"code": "ABD", "name": "Aberdeenshire", "level":"council area", "country": "GB"},    {"code": "AK", "name": "Alaska", "level":"state", "country": "US"}]可能的輸出:code,name,level,countryNSW,New South Wales,state,AUAB,Alberta,province,CAABD,Aberdeenshire,council area,GBAK,Alaska,state,US可能的輸出:"code","name","level","country""NSW","New South Wales","state","AU""AB","Alberta","province","CA""ABD","Aberdeenshire","council area","GB""AK","Alaska","state","US"輸入:[    {"name": "bang", "value": "!", "level": 0},    {"name": "letters", "value": "a,b,c", "level": 0},    {"name": "letters", "value": "x,y,z", "level": 1},    {"name": "bang", "value": "\"!\"", "level": 1}]可能的輸出:name,value,levelbang,!,0letters,"a,b,c",0letters,"x,y,z",1bang,"""!""",0可能的輸出:"name","value","level""bang","!","0""letters","a,b,c","0""letters","x,y,z","1""bang","""!""","1"
查看完整描述

3 回答

?
回首憶惘然

TA貢獻1847條經驗 獲得超11個贊

首先,獲取一個包含對象數組輸入中所有不同對象屬性名稱的數組。這些將是CSV的列:


(map(keys) | add | unique) as $cols

然后,對于對象數組輸入中的每個對象,將獲得的列名映射到對象中的相應屬性。這些將是CSV的行。


map(. as $row | $cols | map($row[.])) as $rows

最后,將列名放在行之前,作為CSV的標題,然后將結果行流傳遞到@csv過濾器。


$cols, $rows[] | @csv

現在都在一起了。請記住使用該-r標志將結果作為原始字符串獲?。?/p>


jq -r '(map(keys) | add | unique) as $cols | map(. as $row | $cols | map($row[.])) as $rows | $cols, $rows[] | @csv'


查看完整回答
反對 回復 2019-11-25
?
holdtom

TA貢獻1805條經驗 獲得超10個贊

瘦的

jq -r '(.[0] | keys_unsorted) as $keys | $keys, map([.[ $keys[] ]])[] | @csv'

要么:


jq -r '(.[0] | keys_unsorted) as $keys | ([$keys] + map([.[ $keys[] ]])) [] | @csv'

細節

在旁邊

描述細節是棘手的,因為jq是面向流的,這意味著它對JSON數據序列(而不是單個值)進行操作。輸入的JSON流將轉換為某種內部類型,并通過過濾器傳遞,然后在程序末尾的輸出流中進行編碼。內部類型不是由JSON建模的,并且不以命名類型存在。最簡單的方法是檢查裸索引(.[])或逗號運算符的輸出(可以通過調試器直接檢查它,但這是基于jq的內部數據類型,而不是JSON背后的概念數據類型) 。


$ jq -c'。[]'<<<'[“ a”,“ b”]'

“一種”

“ b”

$ jq -cn'“ a”,“ b”'

“一種”

“ b”

請注意,輸出不是數組(應該是["a", "b"])。緊湊輸出(該-c選項)表明,每個數組元素(或,過濾器的參數)在輸出中均成為單獨的對象(每個元素在單獨的行上)。


流就像JSON-seq一樣,但是在編碼時使用換行符而不是RS作為輸出分隔符。因此,此內部類型在此答案中由通用術語“序列”指代,其中“流”保留用于編碼的輸入和輸出。


構造過濾器

可以使用以下命令提取第一個對象的鍵:


.[0] | keys_unsorted

密鑰通常會保持其原始順序,但不能保證保留確切的順序。因此,將需要使用它們對對象建立索引以按相同順序獲取值。如果某些對象的鍵順序不同,這也可以防止將值放在錯誤的列中。


為了將鍵作為第一行輸出并使它們可用于索引,它們都存儲在變量中。然后,管道的下一個階段將引用此變量,并使用逗號運算符將標頭添加到輸出流之前。


(.[0] | keys_unsorted) as $keys | $keys, ...

逗號后的表達有點牽連。對象上的索引運算符可以采用字符串序列(例如"name", "value"),返回這些字符串的屬性值序列。$keys是一個數組,而不是一個序列,因此[]可以將其轉換為序列,


$keys[]

然后可以傳遞給 .[]


.[ $keys[] ]

這也產生一個序列,因此使用數組構造函數將其轉換為數組。


[.[ $keys[] ]]

該表達式將應用于單個對象。map()用于將其應用于外部數組中的所有對象:


map([.[ $keys[] ]])

最后,在此階段,它被轉換為序列,因此每個項目在輸出中成為單獨的行。


map([.[ $keys[] ]])[]

為什么將序列捆綁到map唯一的數組中以在外部解綁呢?map產生一個數組;.[ $keys[] ]產生一個序列。將mapfrom 應用于序列.[ $keys[] ]會產生一個值序列數組,但是由于序列不是JSON類型,因此您將獲得一個包含所有值的扁平數組。


["NSW","AU","state","New South Wales","AB","CA","province","Alberta","ABD","GB","council area","Aberdeenshire","AK","US","state","Alaska"]

每個對象的值需要保持分開,以便它們在最終輸出中成為單獨的行。


最后,序列通過@csv格式化程序傳遞。


備用

這些項目可以分離得較晚,而不是早期。代替使用逗號運算符獲取序列(將序列作為正確的操作數傳遞),標頭序列($keys)可以包裝在數組中,并+用于附加值數組。在傳遞給之前,仍然需要將其轉換為序列@csv。


查看完整回答
反對 回復 2019-11-25
?
慕的地6264312

TA貢獻1817條經驗 獲得超6個贊

以下過濾器稍有不同,它將確保將每個值都轉換為字符串。(注意:使用jq 1.5+)


# For an array of many objects

jq -f filter.jq (file)


# For many objects (not within array)

jq -s -f filter.jq (file)

過濾: filter.jq


def tocsv($x):

    $x

    |(map(keys)

        |add

        |unique

        |sort

    ) as $cols

    |map(. as $row

        |$cols

        |map($row[.]|tostring)

    ) as $rows

    |$cols,$rows[]

    | @csv;


tocsv(.)


查看完整回答
反對 回復 2019-11-25
  • 3 回答
  • 0 關注
  • 1207 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號