jjzjj

JSON 到 CSV : variable number of columns per row

coder 2024-06-18 原文

我需要将 JSON 转换为 CSV,其中 JSON 具有可变长度的数组,例如:

JSON 对象:

{"labels": ["label1"]}
{"labels": ["label2", "label3"]}
{"labels": ["label1", "label4", "label5"]}

生成的 CSV:

labels,labels,labels
"label1",,
"label2","label3",
"label1","label4","label5"

源 JSON 中还有许多其他属性,为了简单起见,这只是摘录。

此外,我需要说明的是,该过程必须将 JSON 作为流处理,因为源 JSON 可能非常大 (>1GB)。

我想通过两次传递使用 jq,第一次传递将收集“标签”数组的最大长度,第二次传递将创建 CSV,因为此时结果列的数量是已知的。但是jq没有全局变量的概念,所以我不知道在哪里可以存储运行总计。

我希望能够通过 CLI 在 Windows 上执行此操作。 提前谢谢你。

最佳答案

问题显示了一个 JSON 对象流,因此以下解决方案假设输入文件已经是一个序列,如图所示。这些解决方案也可以很容易地进行调整,以涵盖输入文件包含大量对象的情况,例如正如结语中所讨论的。

两次调用的解决方案

这是一个使用两次 jq 调用的两遍解决方案。如果您有 wsl,演示文稿假定一个类似 bash 的环境:

n=$(jq -n 'reduce (inputs|.labels|length) as $i (-1;
  if $i > . then $i else . end)' stream.json)
jq -nr --argjson n $n '
  def fill($n): . + [range(length;$n)|null];
  [range(0;$n)|"labels"],
  (inputs | .labels | fill($n))
  | @csv' stream.json

假设输入与描述的一样,这可以保证生成有效的 CSV。希望您可以根据需要调整以上内容以适应您的 shell——也许此链接会有所帮助: Assign output of a program to a variable using a MS batch file

使用 input_filename 和一次 jq 调用

不幸的是,jq 没有“倒带”功能,但是 还有一个替代方案:在一次 jq 调用中读取文件两次。这比上面的两次调用解决方案更麻烦,但避免了与后者相关的任何困难。

cat sample.json | jq -nr '

  def fill($n): . + [range(length;$n)|null];
  def max($x): if . < $x then $x else . end;

  foreach (inputs|.labels) as $in ( {n:0};
    if input_filename == "<stdin>" 
    then .n |= max($in|length)
    else .printed+=1
    end;
    if .printed == null then empty
    else .n as $n
    | (if .printed == 1 then [range(0;$n)|"labels"] else empty end),
      ($in | fill($n))
    end)
  | @csv'  -  sample.json

另一种单调用解决方案

以下解决方案使用特殊值(此处为 null)来描述两个流:

(cat stream.json; echo null; cat stream.json) | jq -nr '
  def fill($n): . + [range(length; $n) | null];
  def max($x): if . < $x then $x else . end;

  (label $loop | foreach inputs as $in (0; 
     if $in == null then . else max($in|.labels|length) end;
     if $in == null then ., break $loop else empty end)) as $n
  | [range(0;$n)|"labels"],
    (inputs | .labels | fill($n))
  | @csv '

结语

具有顶级 JSON 数组的文件太大而无法放入内存,可以通过使用 --stream 选项调用 jq 将其转换为数组项的流,例如如下:

jq -cn --stream 'fromstream(1|truncate_stream(inputs))'

关于JSON 到 CSV : variable number of columns per row,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56569222/

有关JSON 到 CSV : variable number of columns per row的更多相关文章

  1. ruby - 用逗号、双引号和编码解析 csv - 2

    我正在使用ruby​​1.9解析以下带有MacRoman字符的csv文件#encoding:ISO-8859-1#csv_parse.csvName,main-dialogue"Marceu","Giveittohimóhe,hiswife."我做了以下解析。require'csv'input_string=File.read("../csv_parse.rb").force_encoding("ISO-8859-1").encode("UTF-8")#=>"Name,main-dialogue\r\n\"Marceu\",\"Giveittohim\x97he,hiswife.\"\

  2. ruby - 我可以使用 Ruby 从 CSV 中删除列吗? - 2

    查看Ruby的CSV库的文档,我非常确定这是可能且简单的。我只需要使用Ruby删除CSV文件的前三列,但我没有成功运行它。 最佳答案 csv_table=CSV.read(file_path_in,:headers=>true)csv_table.delete("header_name")csv_table.to_csv#=>ThenewCSVinstringformat检查CSV::Table文档:http://ruby-doc.org/stdlib-1.9.2/libdoc/csv/rdoc/CSV/Table.html

  3. ruby-on-rails - Rails HTML 请求渲染 JSON - 2

    在我的Controller中,我通过以下方式在我的index方法中支持HTML和JSON:respond_todo|format|format.htmlformat.json{renderjson:@user}end在浏览器中拉起它时,它会自然地以HTML呈现。但是,当我对/user资源进行内容类型为application/json的curl调用时(因为它是索引方法),我仍然将HTML作为响应。如何获取JSON作为响应?我还需要说明什么? 最佳答案 您应该将.json附加到请求的url,提供的格式在routes.rb的路径中定义。这

  4. ruby CSV : How can I read a tab-delimited file? - 2

    CSV.open(name,"r").eachdo|row|putsrowend我得到以下错误:CSV::MalformedCSVErrorUnquotedfieldsdonotallow\ror\n文件名是一个.txt制表符分隔文件。我是专门做的。我有一个.csv文件,我转到excel,并将文件保存为.txt制表符分隔的文件。所以它是制表符分隔的。CSV.open不应该能够读取制表符分隔的文件吗? 最佳答案 尝试像这样指定字段分隔符:CSV.open("name","r",{:col_sep=>"\t"}).eachdo|row|

  5. ruby-on-rails - 如何使用 Rack 接收 JSON 对象 - 2

    我有一个非常简单的RubyRack服务器,例如:app=Proc.newdo|env|req=Rack::Request.new(env).paramspreq.inspect[200,{'Content-Type'=>'text/plain'},['Somebody']]endRack::Handler::Thin.run(app,:Port=>4001,:threaded=>true)每当我使用JSON对象向服务器发送POSTHTTP请求时:{"session":{"accountId":String,"callId":String,"from":Object,"headers":

  6. ruby - 如何使用 Ruby 将 CSV 文件读入 HTML 表格? - 2

    我正在尝试将一个简单的CSV文件读入HTML表格以在浏览器中显示,但我遇到了麻烦。这就是我正在尝试的:Controller:defshow@csv=CSV.open("file.csv",:headers=>true)end查看:输出:NameStartDateEndDateQuantityPostalCode基本上我只获取标题,而不会读取和呈现CSV正文。 最佳答案 这最终成为最终解决方案:Controller:defshow#OpenaCSVfile,andthenreaditintoaCSV::Tableobjectforda

  7. ruby - 用 YAML.load 解析 json 安全吗? - 2

    我正在使用ruby2.1.0我有一个json文件。例如:test.json{"item":[{"apple":1},{"banana":2}]}用YAML.load加载这个文件安全吗?YAML.load(File.read('test.json'))我正在尝试加载一个json或yaml格式的文件。 最佳答案 YAML可以加载JSONYAML.load('{"something":"test","other":4}')=>{"something"=>"test","other"=>4}JSON将无法加载YAML。JSON.load("

  8. ruby-on-rails - 使用 RSpec 测试 CSV.generate - 2

    我在Rails3.1项目中有以下助手-我只是想知道是否有办法测试CSV.generate调用。我很想说我知道如何去做,但事实是我什至不知道从哪里开始。任何想法表示赞赏。require'csv'moduleAdmin::PurchasesHelperdefcsv_purchase_listcolumns=['course','amount','first_name','last_name','contact_phone','contact_mobile','created_at']CSV.generate(:col_sep=>";",:row_sep=>"\r\n",:headers=>

  9. ruby - 如何从 ARGF 读取 csv - 2

    在Ruby1.9中,我如何从ARGF中读取CSV?我尝试了以下方法,但没有打印任何内容:require'csv'CSV(ARGF).readdo|row|prowendhttp://www.ruby-doc.org/core-1.9.3/ARGF.htmlhttp://ruby-doc.org/stdlib-1.9.2/libdoc/csv/rdoc/CSV.html 最佳答案 如果你想偷懒你可以试试:CSV.new(ARGF.file).eachdo|row|...end来源:http://www.ruby-doc.org/std

  10. ruby - 如何跳过 CSV 文件的第一行并将第二行作为标题 - 2

    有没有办法跳过CSV文件的第一行,让第二行作为标题?我有一个CSV文件,第一行是日期,第二行是标题,所以我需要能够在遍历它时跳过第一行。我尝试使用slice但它会将CSV转换为数组,我真的很想将其读取为CSV,以便我可以利用header。 最佳答案 根据您的数据,您可以使用另一种方法和skip_lines-option此示例跳过所有以#开头的行require'csv'CSV.parse(DATA.read,:col_sep=>';',:headers=>true,:skip_lines=>/^#/#Markcomments!)do|

随机推荐