如何在ruby中减去两个json文件

时间:2015-10-14 15:02:48

标签: ruby

我想基本上减去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将嵌套在BOTH文件中的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

1 个答案:

答案 0 :(得分: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"
         }
       }
     }

然后:

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