ruby-on-rails - Json 到 csv。如何转换?

标签 ruby-on-rails ruby

我在将 Json(具有嵌套值)转换为 CSV 文件时遇到了一些麻烦(我想要第一行的标题和下面的 json 值)。 我几乎做到了,但我的输出中仍然存在一些问题。 我写下了到目前为止所做的一切,希望这能让您更轻松地完成任务。

这是 json :

[
  {
    "id": 0,
    "email": "colleengriffith@quintity.com",
    "tags": [
             "consectetur",
             "quis"
    ],
    "profiles": {
      "facebook": {
        "id": 0,
        "picture": "//fbcdn.com/a2244bc1-b10c-4d91-9ce8-184337c6b898.jpg"
      },
      "twitter": {
        "id": 0,
        "picture": "//twcdn.com/ad9e8cd3-3133-423e-8bbf-0602e4048c22.jpg"
      }
    }
  },
      {
    "id": 1,
    "email": "maryellengriffin@ginkle.com",
    "tags": [
             "veniam",
             "elit",
             "mollit"
    ],
    "profiles": {
      "facebook": {
        "id": 1,
        "picture": "//fbcdn.com/12e070e0-21ea-4663-97d0-46bc9c7b67a4.jpg"
      },
      "twitter": {
        "id": 1,
        "picture": "//twcdn.com/3057792f-5dfb-4c4b-86b5-cce4d6bbf7ac.jpg"
      }
    }
  }
]

和我想要的输出:

id,email,tags,profiles.facebook.id,profiles.facebook.picture,profiles.twitter.id,profiles.twitter.picture
0,colleengriffith@quintity.com,"consectetur,quis",0,//fbcdn.com/a2244bc1-b10c-4d91-9ce8-184337c6b898.jpg,0,//twcdn.com/ad9e8cd3-3133-423e-8bbf-0602e4048c22.jpg
1,maryellengriffin@ginkle.com,"veniam,elit,mollit",1,//fbcdn.com/12e070e0-21ea-4663-97d0-46bc9c7b67a4.jpg,1,//twcdn.com/3057792f-5dfb-4c4b-86b5-cce4d6bbf7ac.jpg

这是我到目前为止的结果:

require 'csv'
require 'json'
require 'set'

def get_recursive_keys(hash, nested_key=nil)
  hash.each_with_object([]) do |(k,v),keys|
    k = "#{nested_key}.#{k}" unless nested_key.nil?
      if v.is_a? Hash
      keys.concat(get_recursive_keys(v, k))
    else
      keys << k
    end
  end
end

json = JSON.parse(File.open("live.json").read)
headings = Set.new
json.each do |hash|
  headings.merge(get_recursive_keys(hash))
end

CSV.open('file3.csv', 'w') do |csv|
  csv << headings
  json.each do |hash|
    row = {}
    headings.each do |heading|
      row[heading] = nil
    end
    hash.each do |k,v|
      row[k] = v.to_s.gsub(/\r\n?/, "").delete("\n").delete("\r")
    end
    csv << row.values
  end
end

当我运行时,我得到这个:

id,email,tags,profiles.facebook.id,profiles.facebook.picture,profiles.twitter.id,profiles.twitter.picture
0,colleengriffith@quintity.com,"[""consectetur"", ""quis""]",,,,,"{""facebook""=>{""id""=>0, ""picture""=>""//fbcdn.com/a2244bc1-b10c-4d91-9ce8-184337c6b898.jpg""}, ""twitter""=>{""id""=>0, ""picture""=>""//twcdn.com/ad9e8cd3-3133-423e-8bbf-0602e4048c22.jpg""}}"
1,maryellengriffin@ginkle.com,"[""veniam"", ""elit"", ""mollit""]",,,,,"{""facebook""=>{""id""=>1, ""picture""=>""//fbcdn.com/12e070e0-21ea-4663-97d0-46bc9c7b67a4.jpg""}, ""twitter""=>{""id""=>1, ""picture""=>""//twcdn.com/3057792f-5dfb-4c4b-86b5-cce4d6bbf7ac.jpg""}}"

所以我确实拥有我需要的一切,但是,我仍然有括号和引号,我想将它们从 csv 文件中删除。

如果有人有想法或提示,那就太好了!

感谢任何帮助,

谢谢。

最佳答案

Set 被明确记录为无序,因此您应该在填充标题后立即将其转换为 Array。是的,当前的标准实现是有序的,但你最好避免依赖于实现的假设。因此,第一步是确保 headings 在我们对其进行任何操作之前保证具有一致的顺序:

headings = headings.to_a
CSV.open('file3.csv', 'w') do |csv|
  ...
end

然后您只需要解决如何在将数组和散列编码到 CSV 的过程中对其进行编码。您可以使用 Hash#dig找到你想要的嵌套值,然后用简单的 Array#join 修补任何数组调用:

json.each do |hash|
  row = headings.map do |h|
    v = hash.dig(*h.split('.'))       # Dig out the (possibly) nested value
    v.is_a?(Array) ? v.join(',') : v  # Fix up arrays
  end
  csv << row
end

当然,我们仍在做一些假设(“标签” 中没有逗号,JSON 键中没有句点,......)。


您还可以将 header 存储为数组,这样您就不必一直拆分。然后在构建标题行时需要加入 join('.'):

add_dots = ->(a) { a.join('.') }
csv << headings.map(&add_dots)

并且在构建 v 时只是展开数组:

v = hash.dig(*h)

并调整 get_recursive_keys 以使用数组而不是句点分隔的字符串。

关于ruby-on-rails - Json 到 csv。如何转换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47930694/

相关文章:

ruby-on-rails - current_user 和 active_admin

ruby - ruby mixin 中奇怪的继承

ruby-on-rails - 当用户选择 "#"井号键时,Twilio Call 断开连接

ruby-on-rails - 设计 “Sign In”表单错误地显示 “Invalid Invalid email or password”错误消息

ruby - ruby 中的 fork 和线程

ruby-on-rails - 未定义的方法 `to_i' 与来自控制台的设计

html - 替换 rails scaffold 样式表内容

ruby-on-rails - rake 任务使用命名空间耗尽命名空间

ruby-on-rails - 使用 Rspec、NiftyAuthentication 进行测试

ruby-on-rails - Rails 服务器无法运行 - 找不到 gem 错误