如何将多个哈希合并到一个有效的JSON文件中?

时间:2014-06-18 21:36:45

标签: ruby json hash mechanize

我正在使用以下代码生成一个JSON文件,其中包含特定网站的所有类别信息。

require 'mechanize'

@categories_hash = {}
@categories_hash['category'] ||= {}
@categories_hash['category']['id'] ||= {}
@categories_hash['category']['name'] ||= {}
@categories_hash['category']['group'] ||= {}
@categories_hash['category']['search_attributes'] ||= {}

# Initialize Mechanize object
a = Mechanize.new

# Open file and begin
File.open("json/booyah/#{Time.now.strftime '%Y%m%d%H%M%S'}_booyah_categories.json", 'w') do |f|
  puts '# Writing category data to JSON file'

  # Begin scraping
  a.get('http://www.marktplaats.nl/') do |page|
    groups = page.search('//*[(@id = "navigation-categories")]//a')
    groups.each_with_index do |group, index_1|

      a.get(group[:href]) do |page_2|
        categories = page_2.search('//*[(@id = "category-browser")]//a')
        categories.each_with_index do |category, index_2|

          a.get(category[:href]) do |page_3|
            search_attributes = page_3.search('//*[contains(concat( " ", @class, " " ), concat( " ", "heading", " " ))]')

            search_attributes.each_with_index do |attribute, index_3|
              @categories_hash['category']['id'] = "#{index_1}_#{index_2}"
              @categories_hash['category']['name'] = category.text
              @categories_hash['category']['group'] = group.text
              @categories_hash['category']['search_attributes'][index_3] = attribute.text unless attribute.text == 'Outlet '
            end

            # Uncomment if you want to see what's being written
            puts @categories_hash['category'].to_json

            # Write the converted Hash to the JSON file
            f.write(@categories_hash['category'].to_json)
          end
        end
      end
    end
  end

  puts '|-----------> Done.'

end

puts '# Finished.'

此代码生成以下无效 JSON文件。查看完整的JSON文件here。它看起来像这样:

{
  "id": "0_0",
  "name": "Boeken en Bijbels",
  "group": "Antiek en Kunst",
  "search_attributes": {
    "0": "Prijs van/tot",
    "1": "Groep en Rubriek",
    "2": "Aangeboden sinds"
  }
}{
  "id": "0_1",
  "name": "Emaille",
  "group": "Antiek en Kunst",
  "search_attributes": {
    "0": "Prijs van/tot",
    "1": "Groep en Rubriek",
    "2": "Aangeboden sinds"
  }
}{
  "id": "0_2",
  "name": "Gereedschap en Instrumenten",
  "group": "Antiek en Kunst",
  "search_attributes": {
    "0": "Prijs van/tot",
    "1": "Groep en Rubriek",
    "2": "Aangeboden sinds"
  }
}{...}

我希望输出有效JSON,如下所示:

[
  {
    "id": "0_0",
    "name": "Boeken en Bijbels",
    "group": "Antiek en Kunst",
    "search_attributes": {
      "0": "Prijs van/tot",
      "1": "Groep en Rubriek",
      "2": "Aangeboden sinds"
    }
  },
  {
    "id": "0_1",
    "name": "Emaille",
    "group": "Antiek en Kunst",
    "search_attributes": {
      "0": "Prijs van/tot",
      "1": "Groep en Rubriek",
      "2": "Aangeboden sinds"
    }
  },
  {
    "id": "0_2",
    "name": "Gereedschap en Instrumenten",
    "group": "Antiek en Kunst",
    "search_attributes": {
      "0": "Prijs van/tot",
      "1": "Groep en Rubriek",
      "2": "Aangeboden sinds"
    }
  },
  {...}
]

问题是,我该如何做到这一点?

更新

非常感谢maerics提出answer

这是稍微更新但工作的代码:

require 'mechanize'

@categories_hash = {}
@categories_hash['category'] ||= {}
@categories_hash['category']['id'] ||= {}
@categories_hash['category']['name'] ||= {}
@categories_hash['category']['group'] ||= {}
@categories_hash['category']['search_attributes'] ||= {}

@hashes = []

# Initialize Mechanize object
a = Mechanize.new

# Begin scraping
a.get('http://www.marktplaats.nl/') do |page|
  groups = page.search('//*[(@id = "navigation-categories")]//a')
  groups.each_with_index do |group, index_1|

    a.get(group[:href]) do |page_2|
      categories = page_2.search('//*[(@id = "category-browser")]//a')
      categories.each_with_index do |category, index_2|

        a.get(category[:href]) do |page_3|
          search_attributes = page_3.search('//*[contains(concat( " ", @class, " " ), concat( " ", "heading", " " ))]')

          search_attributes.each_with_index do |attribute, index_3|
            item = {
              id: "#{index_1}_#{index_2}",
              name: category.text,
              group: group.text,
              :search_attributes => {
                :index_3.to_s => "#{attribute.text unless attribute.text == 'Outlet '}"
              }
            }

            @hashes << item

            puts item

          end
        end
      end
    end
  end
end

# Open file and begin
File.open("json/light/#{Time.now.strftime '%Y%m%d%H%M%S'}_light_categories.json", 'w') do |f|
  puts '# Writing category data to JSON file'
  f.write(@hashes.to_json)
  puts '|-----------> Done.'
end

puts '# Finished.'

1 个答案:

答案 0 :(得分:2)

使用内置Ruby JSON library

require 'json'
hashes = []
all_hashes.each { |h| hashes << h }
print hashes.to_json

或者,在极端情况下,您的哈希值不适合可用内存(伪代码):

print '['
for each JSON hash H
  print H
  print ',' unless H is the last of the set
print ']'