Ruby on rails 如何从json文件中收集标题

Ruby on rails 如何从json文件中收集标题,ruby-on-rails,ruby,Ruby On Rails,Ruby,我正在尝试将json文件更改为CSV。以下是我的Json: [ { "id": 0, "email": "colleengriffith@quintity.com", "tags": [ "consectetur", "quis" ], "profiles": { "facebook": { "id": 0, "picture": "//fbcdn.com/a2244bc1-b10c-

我正在尝试将json文件更改为CSV。以下是我的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"
       }
     }
   }
 ]
我首先要做的就是收集标题。以下是我尝试过的:

json = JSON.parse(File.open("live.json").read)
headings = SortedSet.new
json.each do |hash|
  headings.merge(hash.values)
end
它返回给我
#

然后,我试图理解发生了什么(顺便说一句,我没有),但我发现当我要求我的
json.values
时,我没有嵌套的值。以下是我所拥有的:

id
email
tags
profiles
预期产出为:

id, email, tags, profiles.facebook.id, profiles.facebook.picture, profiles.twitter.id, profiles.twitter.picture
所以我的问题是,有人知道如何获得这些标题吗?有没有一种不使用SortedSet的简单方法来获取它们


非常感谢

您可以这样做:

json = <<-END
[
  {
    "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"
       }
     }
   }
 ]
END

CSV.generate do |csv| 
  csv << [:id, :email, :tags, :profiles] # add headers with order
  JSON.parse(json).each do |item| 
    csv << [item['id'], item['email'], item['tags'].join(','), item['profiles']] # add rows with the same order
  end
end
json = JSON.parse(File.open("live.json").read)
headings = SortedSet.new
json.each do |hash|
  headings.merge(get_recursive_keys(hash))
end
但你必须决定如何处理个人资料

已更新

CSV.generate do |csv| 
  csv << ['id', 'email', 'tags', 'profiles.facebook.id', 'profiles.facebook.picture', 'profiles.twitter.id', 'profiles.twitter.picture'] 
  JSON.parse(json).each do |item| 
    csv << [item['id'], item['email'], item['tags'].join(','), item['profiles']['facebook']['id'], item['profiles']['facebook']['picture'], item['profiles']['twitter']['id'], item['profiles']['twitter']['picture']] 
  end
end

对于任何嵌套级别的哈希:

get = ->(hash, prefix = nil) do
        hash.flat_map do |k, v|
          v.is_a?(Hash) ? get.(v, k) : [prefix, k].compact.join('.')
        end
      end

json.map(&get)
#⇒ array of titles in each hash
json.map(&get).first
#⇒ ["id", "email", "tags",
#   "facebook.id", "facebook.picture",
#   "twitter.id", "twitter.picture"]

使用Get\u recursive\u keys方法获取嵌套键

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
现在键的标题:

#<SortedSet: {"email", "id", "profiles.facebook.id", "profiles.facebook.picture", "profiles.twitter.id", "profiles.twitter.picture", "tags"}>
#

您希望得到什么样的确切输出?请说明您的预期输出。您不可能通过调用
hash.values
获得
id
电子邮件
等。我对其进行了编辑,以向您显示我希望得到的输出。谢谢您的回答。我已经决定了如何处理个人资料,我需要收集这些资料,收集的方式与我的输出方式相同。谢谢你回答这个问题,它确实起到了作用。然而,你写的东西在我脑子里不是那么清楚。。。你能再给我解释一下吗?我不知道我能补充些什么使它更明确
get
lambda递归提取密钥并用点连接它们。我喜欢您编写代码的方式。但我有一个问题。当我运行你的代码时,我的标题变量等于
你知道吗?我做错什么了吗?@RaphaëlFOSSE嘿,我只是用p标题而不是puts标题:)对!哈哈,但是,
标签
没有出现在我的输出中,正如我所看到的,你的标签也没有出现在我的输出中。哦,没有注意到,对不起。再次感谢!您正在使用外部局部变量滥用
each
,请使用
json.each_with_object(SortedSet.new){| hash,set | set.merge(get_recursive_keys(hash))}
json = JSON.parse(File.open("live.json").read)
headings = SortedSet.new
json.each do |hash|
  headings.merge(get_recursive_keys(hash))
end
#<SortedSet: {"email", "id", "profiles.facebook.id", "profiles.facebook.picture", "profiles.twitter.id", "profiles.twitter.picture", "tags"}>