2017-07-26 27 views
0

我做了一個簡單的Rake任務來解析一些JSON,我用它來將一些屬性應用到遊戲集合中。rake任務來解析JSON,一些對象可能會丟失

爲了避免在這個塊中出現大量的JSON,JSON可以預覽herehere - 這些來自Steam Store的API返回遊戲細節。 NilClass`上:我耙時,我只是跟兩個信息存在於每一個記錄(假設它是一個成功)

desc 'update steam game info' 

namespace :update_steam_games do 

    task scrape_info: :environment do 
    require 'open-uri' 
    #require 'nokogiri' 
    require 'json' 

    games = SteamGame.first(10) 
    games.each do |game| 
     base_url = "http://store.steampowered.com/api/appdetails?appids=#{game['appid']}" 
     puts "base_url: #{base_url}" 
     results = open(base_url) { |f| 
      result = JSON.parse(f.read) 
      puts result.inspect 
      next if result[game['appid'].to_s]['success'] == false 
      type = result[game['appid'].to_s]['data']['type'] 
      detailed_description = result[game['appid'].to_s]['data']['detailed_description'] 
      about_the_game = result[game['appid'].to_s]['data']['about_the_game'] 
      short_description = result[game['appid'].to_s]['data']['short_description'] 
      supported_languages = result[game['appid'].to_s]['data']['supported_languages'] 
      if !result[game['appid'].to_s]['data']['dlc'].nil? 
       dlc = result[game['appid'].to_s]['data']['dlc'].flatten 
      end 
      is_free = result[game['appid'].to_s]['data']['is_free'] 
      required_age = result[game['appid'].to_s]['data']['required_age'] 
      genres = result[game['appid'].to_s]['data']['genres'].map { |g| g['description'] } 
      developers = result[game['appid'].to_s]['data']['developers'] 
      publishers = result[game['appid'].to_s]['data']['publishers'] 
      windows = result[game['appid'].to_s]['data']['platforms']['windows'] 
      mac = result[game['appid'].to_s]['data']['platforms']['mac'] 
      metacritic_score = result[game['appid'].to_s]['data']['metacritic']['score'] 
      metacritic_link = result[game['appid'].to_s]['data']['metacritic']['url'] 
      #game.update_attributes(genres: genres, detailed_description: detailed_description) 

      puts game.inspect 
     } 
     end 
    end 
end 

的當前錯誤,我得到的是 NoMethodError: undefined method []」爲無工作第34行 - 這也是屬性賦值的結束,所以我不確定它是否與該行直接相關。

我確實意識到我試圖存儲一個布爾值作爲整數,並已修復它,但現在得到這個錯誤。

我已經試過一切包裝成一個if XXX .present?包裝,但後來我得到了如下

desc 'update steam game info' 

namespace :update_steam_games do 

    task scrape_info: :environment do 
    require 'open-uri' 
    #require 'nokogiri' 
    require 'json' 

    games = SteamGame.first(10) 
    games.each do |game| 
     base_url = "http://store.steampowered.com/api/appdetails?appids=#{game['appid']}" 
     puts "base_url: #{base_url}" 
     results = open(base_url) { |f| 
      result = JSON.parse(f.read) 
      puts result.inspect 
      next if result[game['appid'].to_s]['success'] == false 
      if type = result[game['appid'].to_s]['data']['type'].present? 
       type = result[game['appid'].to_s]['data']['type'] 
      end 
      if detailed_description = result[game['appid'].to_s]['data']['detailed_description'].present? 
       detailed_description = result[game['appid'].to_s]['data']['detailed_description'] 
      end 
      if about_the_game = result[game['appid'].to_s]['data']['about_the_game'].present? 
       about_the_game = result[game['appid'].to_s]['data']['about_the_game'] 
      end 
      if short_description = result[game['appid'].to_s]['data']['short_description'].present? 
       short_description = result[game['appid'].to_s]['data']['short_description'] 
      end 
      if supported_languages = result[game['appid'].to_s]['data']['supported_languages'].present? 
       supported_languages = result[game['appid'].to_s]['data']['supported_languages'] 
      end 
      if result[game['appid'].to_s]['data']['dlc'].present?.present? 
        dlc = result[game['appid'].to_s]['data']['dlc'].flatten 
      end 
      if is_free = result[game['appid'].to_s]['data']['is_free'].present? 
       is_free = result[game['appid'].to_s]['data']['is_free'] 
      end 
      if required_age = result[game['appid'].to_s]['data']['required_age'].present? 
       required_age = result[game['appid'].to_s]['data']['required_age'] 
      end 
      if genres = result[game['appid'].to_s]['data']['genres'].map { |g| g['description'] }.present? 
       genres = result[game['appid'].to_s]['data']['genres'].map { |g| g['description'] } 
      end 
      if developers = result[game['appid'].to_s]['data']['developers'].present? 
       developers = result[game['appid'].to_s]['data']['developers'] 
      end 
      if publishers = result[game['appid'].to_s]['data']['publishers'].present? 
       publishers = result[game['appid'].to_s]['data']['publishers'] 
      end 
      if windows = result[game['appid'].to_s]['data']['platforms']['windows'].present? 
       windows = result[game['appid'].to_s]['data']['platforms']['windows'] 
      end 
      if mac = result[game['appid'].to_s]['data']['platforms']['mac'].present? 
       mac = result[game['appid'].to_s]['data']['platforms']['mac'] 
      end 
      if metacritic_score = result[game['appid'].to_s]['data']['metacritic']['score'].present? 
       metacritic_score = result[game['appid'].to_s]['data']['metacritic']['score'] 
      end 
      if metacritic_link = result[game['appid'].to_s]['data']['metacritic']['url'].present? 
       metacritic_link = result[game['appid'].to_s]['data']['metacritic']['url'] 
      end 
      #game.update_attributes(genres: genres, detailed_description: detailed_description) 

      puts game.inspect 
     } 
     end 
    end 
end 

但我其實還是結了同樣的問題,除了這樣的事實,我不能確定我怎麼會甚至將它傳遞給game.update_attributes而不知道它是否存在。

我該如何檢查實際存在的問題,並減少冗餘?

的JSON

如果你不想點擊我在這裏提供的JSON樣本的鏈接。我刪除了一些臃腫的東西。它開頭的10是動態ID。

"10": { 
    "success": true, 
    "data": { 
     "type": "game", 
     "name": "Counter-Strike", 
     "steam_appid": 10, 
     "required_age": 0, 
     "is_free": false, 
     "detailed_description": "Play the world's number 1 online action game. Engage in an incredibly realistic brand of terrorist warfare in this wildly popular team-based game. Ally with teammates to complete strategic missions. Take out enemy sites. Rescue hostages. Your role affects your team's success. Your team's success affects your role.", 
     "about_the_game": "Play the world's number 1 online action game. Engage in an incredibly realistic brand of terrorist warfare in this wildly popular team-based game. Ally with teammates to complete strategic missions. Take out enemy sites. Rescue hostages. Your role affects your team's success. Your team's success affects your role.", 
     "short_description": "", 
     "supported_languages": "English, French, German, Italian, Spanish, Simplified Chinese, Traditional Chinese, Korean", 
     "header_image": "http://cdn.akamai.steamstatic.com/steam/apps/10/header.jpg?t=1447887426", 
     "website": null, 
     "pc_requirements": { 
     "minimum": "\n\t\t\t<p><strong>Minimum:</strong> 500 mhz processor, 96mb ram, 16mb video card, Windows XP, Mouse, Keyboard, Internet Connection<br /></p>\n\t\t\t<p><strong>Recommended:</strong> 800 mhz processor, 128mb ram, 32mb+ video card, Windows XP, Mouse, Keyboard, Internet Connection<br /></p>\n\t\t\t" 
     }, 
     "mac_requirements": { 
     "minimum": "Minimum: OS X Snow Leopard 10.6.3, 1GB RAM, 4GB Hard Drive Space,NVIDIA GeForce 8 or higher, ATI X1600 or higher, or Intel HD 3000 or higher Mouse, Keyboard, Internet Connection" 
     }, 
     "linux_requirements": { 
     "minimum": "Minimum: Linux Ubuntu 12.04, Dual-core from Intel or AMD at 2.8 GHz, 1GB Memory, nVidia GeForce 8600/9600GT, ATI/AMD Radeaon HD2600/3600 (Graphic Drivers: nVidia 310, AMD 12.11), OpenGL 2.1, 4GB Hard Drive Space, OpenAL Compatible Sound Card" 
     }, 
     "developers": [ 
     "Valve" 
     ], 
     "publishers": [ 
     "Valve" 
     ], 
     "price_overview": { 
     "currency": "USD", 
     "initial": 999, 
     "final": 999, 
     "discount_percent": 0 
     }, 
     "packages": [ 
     7 
     ], 
     "package_groups": [ 
     { 
      "name": "default", 
      "title": "Buy Counter-Strike", 
      "description": "", 
      "selection_text": "Select a purchase option", 
      "save_text": "", 
      "display_type": 0, 
      "is_recurring_subscription": "false", 
      "subs": [ 
      { 
       "packageid": 7, 
       "percent_savings_text": "", 
       "percent_savings": 0, 
       "option_text": "Counter-Strike: Condition Zero - $9.99", 
       "option_description": "", 
       "can_get_free_license": "0", 
       "is_free_license": false, 
       "price_in_cents_with_discount": 999 
      } 
      ] 
     } 
     ], 
     "platforms": { 
     "windows": true, 
     "mac": true, 
     "linux": true 
     }, 
     "metacritic": { 
     "score": 88, 
     "url": "http://www.metacritic.com/game/pc/counter-strike?ftag=MCD-06-10aaa1f" 
     } 
    } 
} 

更新

我意識到,我不能檢查的platform - windows如果platform不存在,所有腦幹。現在代碼已成功執行,但是,由於大量參數可能會或可能不會在每次傳遞中丟失,因此我正在寫一個問題。

什麼是正確的方法來做到這一點,而不是if塊到處?

更新

我的代碼現在工作後,我意識到我愣神把if塊中的變量definement部分的周圍。

但是,這仍然是多餘的。有沒有適當的方式來做到這一點,或者這是好的嗎?

+0

檢查此https://stackoverflow.com/a/6225321/5113690 –

回答

0
games = SteamGame.first(10) 
games.each do |game| 
    base_url = "http://store.steampowered.com/api/appdetails?appids=#{game['appid']}" 
    puts "base_url: #{base_url}" 
    results = open(base_url) { |f| 
     result = JSON.parse(f.read) 
     game_appid = game[:appid].to_s 
     result_for_appid = result[game_appid] 
     result_data = result_for_appid[:data] 
     puts result.inspect 
     next if result_for_appid[:success] == false 
     type = result_data[:type] 
     detailed_description = result_data[:detailed_description] 
     about_the_game = result_data[:about_the_game] 
     short_description = result_data[:short_description] 
     supported_languages = result_data[:supported_languages] 
     if result_data[:dlc].present? 
      dlc = result_data[:dlc].flatten 
     end 
     is_free = result_data[:is_free] 
     required_age = result_data[:required_age] 
     # genres = result_data[:genres].map { |g| g[:description] } 
     # Your provided JSON didn't contain 'genres' inside 'data' 
     developers = result_data[:developers] 
     publishers = result_data[:publishers] 
     windows = result_data[:platforms][:windows] 
     mac = result_data[:platforms][:mac] 
     metacritic_score = result_data[:metacritic][:score] 
     metacritic_link = result_data[:metacritic][:url] 
     # game.update_attributes(genres: genres, detailed_description: detailed_description) 
     # Your provided JSON didn't contain 'genres' inside 'data' so no update for this 
     game.update_attributes(detailed_description: detailed_description) 

     puts game.inspect 
    } 
    end 
end 

這幾個小技巧: DRY - 不要重複自己 您可以訪問JSON鍵作爲 你沒有「流派在你提供的JSON 符號您不必使用IF的 - 當沒有數據時你會得到:variable = nil。稍後你可以更新有關變量值的屬性。

+0

謝謝 - 是的,流派的東西其實是我成功的問題的一部分。我的問題是現在,當它到達任何空白列時,我得到的響應類似於 'NoMethodError:undefined method []'for nil:NilClass'' - 我會嘗試使用您的數據邏輯預定義,因爲我討厭如果塊到處。 – DNorthrup