如何将此json展平为tsv?

use*_*739 -2 csv json flatten export-to-csv jq

我想将此 JSON 压缩为 tsv 文件。

https://www.vi4io.org/assets/io500/2019-06/data.json

问题是每个条目({} 的第一级)都有许多字段/子字段。我不想指定这么多字段名称。并且不能保证所有条目的字段/子字段都相同。因此,我希望结果列包含所有字段/子字段的联合。列名称的顺序应尽可能接近原始 json 文件。(例如,同一字段中的那些子字段应一起列在 tsv 中)。

将此json文件转换为tsv的最佳方法是什么?谢谢。

pea*_*eak 5

这是一个 jq 解决方案,它适用于任何 JSON 对象数组,没有限制,但请参阅下面的“注意事项”。

json2tsv.jq

# Given an array of JSON objects, 
# produce "TSV" rows, with a header row.
# Handle terminal arrays specially if they are flat.


# emit a stream
def json2headers:
  def isscalar: type | . != "array" and . != "object";
  def isflat: all(.[]; isscalar);
  paths as $p
  | getpath($p)
  | if type == "array" and isflat then $p
     elif isscalar and (($p[-1]|type) == "string") then $p
     else empty end ;

def json2array($header):
   [$header[] as $p | (try getpath($p) catch null)] ;

def json2tsv:
  ( [.[] | json2headers] | unique) as $h
  | ([$h[]|join("_") ],
     (.[]
      | json2array($h)
      | map( if type == "array" then map(tostring)|join("|") else tostring end)))
  | @tsv ;
Run Code Online (Sandbox Code Playgroud)

用法

jq -r -L. 'include "json2tsv"; json2tsv' input.json
Run Code Online (Sandbox Code Playgroud)

输出

输入样本非常大,所以在这里我将只显示标题以及一个单独的示例。

标题

find_easy   information_URL information_client_kernel_version   information_client_nodes    information_client_operating_system information_client_operating_system_version information_client_procs_per_node   information_comment information_data    information_ds_network  information_ds_nodes    information_ds_operating_system_version information_ds_software_version information_ds_storage_devices  information_ds_storage_interface    information_ds_storage_type information_ds_volatile_memory_capacity information_embargo_end_date    information_filesystem_name information_filesystem_type information_filesystem_version  information_id  information_institution information_list    information_md_network  information_md_nodes    information_md_operating_system_version information_md_software_version information_md_storage_devices  information_md_storage_interface    information_md_storage_type information_md_volatile_memory_capacity information_note    information_storage_install_date    information_storage_refresh_date    information_storage_vendor  information_submission_date information_submitter   information_system  information_vendorURL   information_whatever    io500_md    io500_score ior_easy_read   ior_easy_write  ior_hard_read   ior_hard_write  mdtest_easy_delete  mdtest_easy_stat    mdtest_easy_write   mdtest_hard_delete  mdtest_hard_read    mdtest_hard_stat    mdtest_hard_write
Run Code Online (Sandbox Code Playgroud)

简短示例

输入.json

[ {a: [1,2], b: {c:3, d: [{e:4},{e:5, f:6}]}},
  {b: {d: [{e:4},{f:6, e:5}], c:3}, a:[101,102] } ]
Run Code Online (Sandbox Code Playgroud) 输出
a   b_c b_d_0_e b_d_1_e b_d_1_f
1|2 3   4   5   6
101|102 3   4   5   6
Run Code Online (Sandbox Code Playgroud)

input.json(德米特里的变体)

[ {a:[1,2],b:{c:3,d:[{e:4},{e:5,f:6}]}},
  {b:{d:[{e:4},{f:6}],c:3},a:[101,102]} ]
Run Code Online (Sandbox Code Playgroud) 输出
a   b_c b_d_0_e b_d_1_e b_d_1_f
1|2 3   4   5   6
101|102 3   4   null    6
Run Code Online (Sandbox Code Playgroud)

不同结构的物体

[ {a: [1,2], b: {c: 3}},
  {a: [4,5], b: {c: {d: 6 } } }
Run Code Online (Sandbox Code Playgroud) 输出
a   b_c b_c_d
1|2 3   null
4|5 {"d":6} 6
Run Code Online (Sandbox Code Playgroud)

注意事项

  • 对于顶级数组中的每个对象,计算所有标量和标量值数组的路径;如果任何此类路径在另一个顶级对象中无效,则输出中的相应值将为null,如上一个示例所示。

  • 平面数组被转换为竖线分隔的值,这样如果输入包含一个数组,例如 ["1|2", ["3|4"],它将与字符串值“1|2|3”无法区分|4" 等。如果这是一个问题,当然可以更改用作数组项的分隔符值的字符。

  • 标题名称可能会发生类似的冲突。

  • jq's@tsv""and生成一个空字符串null,因此如果区分两者很重要,您可能希望map在调用@tsv.