Catalina Cenan
Catalina Cenan

Reputation: 319

Merge three hashes into an existing hash combining values

I'm trying to create a manifest file with all microservices versions,code&name from different json files into an existing one.Please see below the existing .json template:

{
  "name": "MS Suite",
  "version": "2017.1.0"
}

And I want to parse other json files and combine the hashes and merge here which should look like:

{
 "name": "MS Suite",
 "version": "2017.1.0",
 "components": [
{
  "code": "1x.2017",
  "name": "microservice1",
  "version": "1.1.3-1"
},
{
  "code": "3x.2017",
  "name": "microservice2",
  "version": "1.1.15-1"
},
{
  "code": "2x.2017",
  "name": "microservice3",
  "version": "1.1.17-1
 }  ...
]
}

After hard research I manage to parse these .json files and manage to get a big hash with this code,name,version from all the json files, but I encounter many problems: 1.Can't invert hashes values because it's the same key (code/name/version) so it will return only one row, so right now I have "value": "key" 2.I'm creating this final hash from three arrays so it will create the array with all the codes, all the names and finally all the versions 3.And I also need to merge this into the template pasted above. Right now my function looks like this:

code=[]
name=[]
version=[]
stream.each do |s|
file = File.read("./resources/release/release-updates/#{s}/manifest.json")
data_hash = JSON.parse(file)
data_hash['services'].each do |h|
  code << h['code']
  name << h['name']
  version << h['service-version']
  c = Hash[code.map {|v| [v, 'code']}]
  n = Hash[name.map {|v| [v, 'name']}]
  v = Hash[version.map {|v| [v, 'version']}]
  a  = [c, n, v]
  @result = a.inject(&:merge)#Hash[*a.map(&:to_a).flatten]
end
end
puts @result.to_json

So you notice that the .json files for parsing are stored here: ./resources/release/release-updates/#{s}/manifest.json where s=stream which can be core&processing&packaging. If you want to help you can create 2 or 3 json files in this location and try merging in the template located in the current folder. These 2 or 3 files from where I need to take code,name and service-version are all like this:

 ...
 "services": [{
    "name": "1 Micro service",
    "service-name": "microservice1",
    "code": "1x",
    "service-version": "3.1.3-1",
    "cookbook-name": "microservice1",
    "cookbook-version": "0.2.63",
    "cookbook-repo": "ssh://git..."
}, {
    "name": "2 Micro service",
    "service-name": "microservice2",
    "code": "1x",
    "service-version": "3.1.6-1",
    "cookbook-name": "microservice2",
    "cookbook-version": "0.1.73",
    "cookbook-repo": "ssh://git...."
}...

OUTPUT

{"1x":"code","2x":"code","3x":"code","4x":"code","5x":"code","6x":"code","microservice1":"name","microservice2":"name","microservice3":"name","microservice4":"name","microservice5":"name","microservice6":"name","3.1.3-1":"version","3.1.6-1":"version","3.1.9-1":"version","2017.1.0.0-17_1":"version","2017.1.0.47-RELEASE":"version","1.8.3-1":"version"}

Upvotes: 0

Views: 306

Answers (1)

Vlad Cenan
Vlad Cenan

Reputation: 172

So basically we need to create one hash from the template and another one from the values from the .json files

components = []
stream.each do |s|
file = File.read("path.../#{s}/manifest.json")
data_hash = JSON.parse(file)
components << data_hash['services'].map do |h|
   {
    'code' => h['code'],
    'name' => h['name'],
    'version' => h['service-version']
   }
end
end

the hash from the template

mainfestfile = File.read("path...")
header = JSON.parse(mainfestfile)

and the merge

concatenated = components.flatten
header['components'] = concatenated
puts header.to_json

or save it:

 File.open("./path.json","w") do |f|
  f.puts JSON.pretty_generate(header)
 end

Upvotes: 1

Related Questions