Transferring JSON Data into an array using ruby - ruby

This is my JSON code
{
"jobs": [
{
"id": 1,
"title": "Software Developer",
"applicants": [
{
"id": 1,
"name": "Rich Hickey",
"tags": ["clojure", "java", "immutability", "datomic", "transducers"]
},
{
"id": 2,
"name": "Guido van Rossum",
"tags": ["python", "google", "bdfl", "drop-box"]
}
]
},
{
"id": 2,
"title": "Software Architect",
"applicants": [
{
"id": 42,
"name": "Rob Pike",
"tags": ["plan-9", "TUPE", "go", "google", "sawzall"]
},
{
"id": 2,
"name": "Guido van Rossum",
"tags": ["python", "google", "bdfl", "drop-box"]
},
{
"id": 1337,
"name": "Jeffrey Dean",
"tags": ["spanner", "BigTable", "MapReduce", "deep learning", "massive clusters"]
}
]
}
]
}
I want to put the list of "Jobs" in an array using ruby.
I have the following code so far.
require 'json'
file = File.read(filepath)
data_hash = JSON.parse(file)
How do I iterate on the data_hash and chose what information I want and place it in an array?

You can use Array#each because data_hash['jobs'] contains an array of jobs:
data_hash['jobs'].each {|job| ... }

Like this,
arr = Array.new
data_hash.each { |job|
arr.insert(job['name'])
}

use Array#map for shorter code
data_hash['jobs'].map do |job|
# Do whatever you want with the job here
properties = %w(title applicants)
job.select{ |key| properties.include?(key) }
end

Related

Add new items to multidimensional Ruby hash in loop

Migrating my code to Ruby stuck on the updating this hash with new items inside the multidimensional hash>customers>image>
bannerhash = {
"stooge": "larry",
"toppings": [],
"customers": [
{
"id": 1,
"alt": "Image seo text",
"image": {
"label": "gid:///28663588552955",
"image": "https://cdn.doma.com/s/files/1/0611/2064/3323/files/yellow-pillow-bedside-table_2000x.jpg?v=1637223489"
},
"mainsize": 100
},
{
"id": 2,
"alt": "Image seo text",
"image": {
"label": "gid:///28663588487419",
"image": "https://cdn.doma.com/s/files/1/0611/2064/3323/files/bed-side-table_2000x.jpg?v=1637223489"
},
"mainsize": 100
},
{
"id": 3,
"alt": "image",
"themeposition": "388506648827/posA",
"image": {
"label": "gid:///28663588585723",
"image": "https://cdn.doma.com/s/files/1/0611/2064/3323/files/sunlight-creeps-through-a-bright-living-room_2000x.jpg?v=1637223489"
},
"mainsize": 87
},
{
"id": 4,
"alt": "short width",
"themeposition": "home",
"mainsize": 70,
"image": {
"label": "gid:///28663588454651",
"image": "https://cdn.doma.com/s/files/1/0611/2064/3323/files/modern-and-stylish-design_2000x.jpg?v=1637223489"
},
"quickcss": "#import url(\'https://fonts.googleapis.com/css2?family=Comic+Neue:wght#300&display=swap\');\n.wrapper-4 .--description {font-family: \'Comic Neue\', cursive; }"
}
]
}
Want to update in the loop and the add the "newitem" key with value inside the "image" like
{
"stooge": "larry",
"toppings": [],
"customers": [
{
"id": 1,
"alt": "Image seo text",
"image": {
"label": "gid:///28663588552955",
"image": "https://cdn.doma.com/s/files/1/0611/2064/3323/files/yellow-pillow-bedside-table_2000x.jpg?v=1637223489",
"newitem": "https://cdn.doma.com/s/files/1/0611/2064/3323/files/yellow-pillow-bedside-table_3300x.jpg?v=1637223489"
},
"mainsize": 100
},
{
"id": 2,
"alt": "Image seo text",
"image": {
"label": "gid:///28663588487419",
"image": "https://cdn.doma.com/s/files/1/0611/2064/3323/files/bed-side-table_2000x.jpg?v=1637223489",
"newitem": "https://cdn.doma.com/s/files/1/0611/2064/3323/files/bed-side-table_3300x.jpg?v=1637223489"
},
"mainsize": 100
}
]
}
My workaround code where I am stuck on how ruby update hash inside the each loop. First I catch the inner hash with the "customers" key and know the index and value however stuck on how to add "newitem" inside the "customers" "image" hash
if bannerhash.has_key?(:customers)
puts "found"
bannerhash.each_with_index do |(key, value), index|
if key == :customers
puts "index: #{index} | key: #{key} | value: #{value}"
# STACK Here bannerhash[key].each
end
end
else
puts "banners not found"
end
This seems pretty straightforward. No need to loop over all of the key/value pairs looking for :customers when we can access it directly.
if bannerhash.has_key?(:customers)
bannerhash[:customers].each { |h|
h[:image][:newitem] = "https://cdn.doma.com/s/files/1/0611/2064/3323/files/yellow-pillow-bedside- table_3300x.jpg?v=1637223489"
}
else
puts "banners not found"
end

Merge two hashes in order to create a json file

Hi I want to merge two hashes into a json file which should look like this:
{
"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"
}
]
}
Please find below hash1:
{
"name": "MS Suite",
"version": "2017.1.0"
}
Please find below hash2 which is an array:
[
{
"code": "1x.2017",
"name": "microservice1",
"version": "1.1.3-1"
},
{
"code": "3x.2017",
"name": "microservice2",
"version": "1.1.15-1"
}
]
You're looking for Hash#[]=:
hash = {
"name": "MS Suite",
"version": "2017.1.0"
}
array = [
{
"code": "1x.2017",
"name": "microservice1",
"version": "1.1.3-1"
},
{
"code": "3x.2017",
"name": "microservice2",
"version": "1.1.15-1"
}
]
hash['components'] = array
hash
#=> {: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"}]}
To convert it to json:
require 'json'
hash.to_json
#=> "{\"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\"}]}"

Filter an array in Ruby

In Ruby, I have a hash like below. How can I get the "name" of the "tag" where the tag_type is "LocationTag"? In this case, the returned value would be 'singapore'.
Is the best method just to do:
location = nil
tags.each do |t|
if t["tag_type"] == "LocationTag"
location = t.name
end
end
or does ruby have a better method for filtering hashes?
{
tags: [
{
"id": 81410,
"tag_type": "SkillTag",
"name": "angular.js",
"display_name": "Angular.JS",
"angellist_url": "https:\/\/angel.co\/angular-js"
},
{
"id": 84038,
"tag_type": "SkillTag",
"name": "bootstrap",
"display_name": "Bootstrap",
"angellist_url": "https:\/\/angel.co\/bootstrap"
},
{
"id": 1682,
"tag_type": "LocationTag",
"name": "singapore",
"display_name": "Singapore",
"angellist_url": "https:\/\/angel.co\/singapore"
},
{
"id": 14726,
"tag_type": "RoleTag",
"name": "developer",
"display_name": "Developer",
"angellist_url": "https:\/\/angel.co\/developer"
}
]
}
This will get you the first hit:
tags.detect{|tag| tag['tag_type'] == 'LocationTag'}['name']
This will give you all hits as an array
tags.select{|tag| tag['tag_type'] == 'LocationTag'}.map{|t| t['name']}
Check out the docs for Ruby#Enumerable for more details.
Ruby#Enumerable:detect
Ruby#Enumerable:select
(Thanks #PaulRichter for the comment... it's a nice clarifying addition to the post)
You can use find to stop the iteration once you've found a result:
location = tags.find { |t| t["name"] if t["tag_type"] == "LocationTag" }
Mind the errors that got fixed in the above: t.name and = "LocationTag".

Extracting data from Deeply Nested JSON in Ruby on Rails

Have a Json out put like
{
"query": {
"results": {
"industry": [
{
"id": "112",
"name": "Agricultural Chemicals",
"company": [
{
"name": "Adarsh Plant",
"symbol": "ADARSHPL"
},
{
"name": "Agrium Inc",
"symbol": "AGU"
}
},
]
{
"id": "914",
"name": "Water Utilities",
"company": [
{
"name": "Acque Potabili",
"symbol": "ACP"
},
{
"name": "Water Resources Group",
"symbol": "WRG"
}
]
}
]
}
}
}
Need the out put like - Company Name, Company Symbol, Company id,
Company id name
and example of output would be
Adarsh Plant, ADARSHPL, 112, Agricultural Chemicals
Agrium Inc, AGU, 112, Agricultural Chemicals
Acque Potabili, ACP, 914, Water Utilities
Water Resources Group, WRG, 914, Water Utilities
Any suggestions
There's a typo in your sample json, but we'll talk about it later.
Assuming your json data converted to hash object already like this:
json={
"query"=> {
"results"=> {
"industry"=> [
{
"id"=> "112",
"name"=> "Agricultural Chemicals",
"company"=> [
{
"name"=> "Adarsh Plant",
"symbol"=> "ADARSHPL"
},
{
"name"=> "Agrium Inc",
"symbol"=> "AGU"
}
]
},
{
"id"=> "914",
"name"=> "Water Utilities",
"company"=> [
{
"name"=> "Acque Potabili",
"symbol"=> "ACP"
},
{
"name"=> "Water Resources Group",
"symbol"=> "WRG"
}
]
}
]
}
}
}
You can use inject and map to handle the two level array of industry, inject will iterate the outer array:
json["query"]["results"]["industry"].inject([]){|m,o|
m += o["company"].map{|x| [x["name"],x["symbol"],o["id"],o["name"]]}
}
result is an array of arrays with the order as you wish:
=> [["Adarsh Plant", "ADARSHPL", "112", "Agricultural Chemicals"],
["Agrium Inc", "AGU", "112", "Agricultural Chemicals"],
["Acque Potabili", "ACP", "914", "Water Utilities"],
["Water Resources Group", "WRG", "914", "Water Utilities"]]
If you want get a string delimited by comma, you could chain on .flatten.join(",") at the end.
json["query"]["results"]["industry"].inject([]){|m,o|
m += o["company"].map{|x| [x["name"],x["symbol"],o["id"],o["name"]]}
}.flatten.join(",")
Result:
=> Adarsh Plant,ADARSHPL,112,Agricultural Chemicals,Agrium Inc,AGU,112,Agricultural Chemicals,Acque Potabili,ACP,914,Water Utilities,Water Resources Group,WRG,914,Water Utilities
The typo of your json data:
In the middle }, ] { should be changed to ] },{ .
Convert json to hash
https://stackoverflow.com/a/7964378/3630826

Ruby deep hash looping?

I have a large nested hash in the form below. I need to loop through and pull out the name and url of each repository, but I can't seem to do that. Any suggestions?
Code snippet:
repo_json = get_touched_repos()
repo_hash = JSON.parse(repo_json)
puts repo_hash.class
puts repo_hash['repositories'][0]['name']
The hash:
{
"repositories": [
{
"type": "repo",
"username": "...",
"name": "....",
"owner": "...",
"homepage": "",
"description": "description",
"language": "Java",
"watchers": 2,
"followers": 2,
"forks": 1,
"size":
"open_issues": 0,
"score": 1.0,
"has_downloads": true,
"has_issues": true,
"has_wiki": true,
"fork": false,
"private": false,
"url": "http://my.domain.com/repo/name",
"created": "2012-07-02T17:47:54Z",
"created_at": "2012-07-02T17:47:54Z",
"pushed_at": "2014-03-20T20:09:38Z",
"pushed": "2014-03-20T20:09:38Z"
},
{....}
]
}
You can use Array#each method to do this
repo_hash['repositories'].each do |repo|
puts repo['name']
puts repo['url']
end
To get the names and the URLs in a hash:
name_url_pairs = repo_hash['repositories'].collect do |repo|
{ name: repo['name'], url: repo['url] }
end
Update: Returning a small hash with several extracted values.
Another approach to index by name:
name_hash = Hash[
repo_hash['repositories'].collect do |repo|
[ repo['name'], repo['url'] ]
end
]

Resources