2015-10-14 95 views
1

我想要在ruby中減去兩個json文件,並將區別寫入第三個文件。例如我怎樣才能在ruby中下載兩個json文件

file1.json

{ 
    "id" : "file1", 
    "att1" : { 
    "attA" : { 
     "free_mem" : "1234", 
     "buff_mem" : "5678" 
    }, 
    "attB" : { 
     "name" : "Joe", 
     "location" : "Lab" 
    } 
    } 
} 

file2.json

{ 
    "att1" : { 
    "attA" : { 
     "free_mem" : "3457", 
     "buff_mem" : "6789" 
    } 
    } 
} 

所得flle3.json文件

file3.json

{ 
    "id" : "file1", 
    "att1" : { 
    "attB" : { 
     "name" : "Joe", 
     "location" : "Lab" 
    } 
    } 
} 

這只是一個例子文件。真正的file1.json可能有多個嵌套在att1中的屬性,它們本身可以是嵌套屬性。同樣,我所擁有的file2.json文件可能有多個嵌套在att1中的屬性,它們本身可以是嵌套屬性。但是,每個文件中的嵌套結構是相似的。例如,IOW,attA將嵌套在兩個文件的att1中。謝謝!

編輯回答佩德羅的問題:「你嘗試過什麼到目前爲止」

我試過這個Ruby代碼,但我沒有得到我想要的結果。

require 'rubygems' 
require 'json' 

unless ARGV.count > 1 
    puts "Usage: json_diff.rb json_file_1.json json_file_2.json" 
    puts "AND json_diff.rb json_file_2.json json_file_1.json" 
    exit 
end 


json_a = JSON.parse(File.read(ARGV[0])) 
json_b = JSON.parse(File.read(ARGV[1])) 

array_diff = ["#{json_a}"] - ["#{json_b}"] 

puts array_diff.to_s 

Cary的代碼有效!這是完整的實現。

require 'rubygems' 
require 'json' 

unless ARGV.count > 1 
    puts "Usage: json_diff.rb json_file_1.json json_file_2.json" 
    puts "AND json_diff.rb json_file_2.json json_file_1.json" 
    exit 
end 

def subtract(h1, h2) 
    h1_deep_copy = Marshal.load(Marshal.dump(h1)) 
    recurse(h1_deep_copy, h2) 
    h1_deep_copy 
end 

def recurse(h1, h2) 
    result = h1.keys.map do |k| 
    remove = 
    if !h2.key?(k) 
     remove = false 
    elsif !h1[k].is_a?(Hash) 
     remove = true 
    elsif !h2[k].is_a?(Hash) 
     remove = false 
    else 
     recurse(h1[k], h2[k]) 
    end 
    h1.delete(k) if remove 
    remove 
    end 
    result.uniq == [true] 
end 

h1 = JSON.parse(File.read(ARGV[0])) 
h2 = JSON.parse(File.read(ARGV[1])) 
h1 = subtract(h1, h2) 
puts h1.to_s 
+0

可能重複question/11958374 /從另一個哈希中的相應值中減去哈希數值 – ptierno

+1

如果您具有相同的密鑰但不相同的值,該怎麼辦?考慮到這一點:'{「key1」:「value is string」}'and'{「key1」:{「value」:「is string」}}' –

+0

Jean Bob,沒關係,只要key1不是我想要刪除的屬性。 –

回答

0

比方說,你看這些文件並將它們轉換成哈希h1h2。我們可以執行以下操作來獲得所需的散列。

代碼

def subtract(h1, h2) 
    h1_deep_copy = Marshal.load(Marshal.dump(h1)) 
    recurse(h1_deep_copy, h2) 
    h1_deep_copy 
end 

def recurse(h1, h2) 
    result = h1.keys.map do |k| 
    remove = 
    if !h2.key?(k) 
     false 
    elsif !h1[k].is_a?(Hash) 
     true 
    elsif !h2[k].is_a?(Hash) 
     false 
    else 
     recurse(h1[k], h2[k]) 
    end 
    h1.delete(k) if remove 
    remove 
    end 
    result.uniq == [true] 
end 

正如所指出的,這兩種方法Marshal用於獲得的h1深層副本。

轉換後各JSON串的假設,以哈希我們得到:

h1 = { "id": "file1", 
     "att1": { 
     "attA": { 
      "free_mem": "1234", 
      "buff_mem": "5678" 
     }, 
     "attB": { 
      "name": "Joe", 
      "location": "Lab" 
     } 
     } 
    } 

h2 = { "att1": { 
     "attA": { 
      "free_mem": "3457", 
      "buff_mem": "6789" 
     } 
     } 
    } 

然後:http://stackoverflow.com/的

subtract(h1, h2) 
    #=> {:id=>"file1", :att1=>{:attB=>{:name=>"Joe", :location=>"Lab"}}} 
+0

謝謝,我會試試這個。 –

+0

這不適合我。我得到{「id」=>「file1」,「att1」=> {「attA」=> {「free_mem」=>「1234」,「buff_mem」=>「5678」},「attB」=>名稱「=>」喬「,」位置「=>」實驗室「}}}。我會編輯我的帖子以包含所有代碼,包括Cary的 –

+0

我不明白。你說它在你編輯的問題中起作用了。 –