How make ruby write my JSON correctly? - ruby

How can I make Ruby write the way my JSON is structured?
I want this way:
{
"keywords": [
{
"id": "1" ,
"product": "car"
} ,
{
"id": "2" ,
"product": "mobile"
}
]
}
When i run the code with a 3rd object,
Ruby writes:
{
"keywords": [
{
"id": "1" ,
"product": "car"
} ,
{
"id": "2" ,
"product": "mobile"
}
],"3":"ball"
}
I'm generating the JSON this way:
data_hash.store(3, 'ball')
json_output = data_hash.to_json
file = File.open('keywords.json','w')
file.write(json_output)

You probably want use the following instead of store:
data_hash['keywords'] << { 'id' => '3', 'product' => 'ball' }

Related

How to query array of objects as part of term query

I am using elasticsearch 5.5.0.
Im my index i have data of type attraction part of the json in elastic looks like:
"directions": "Exit the M4 at Junction 1",
"phoneNumber": "03333212001",
"website": "https://www.londoneye.com/",
"postCode": "SE1 7PB",
"categories": [
{
"id": "ce4cf4d0-6ddd-49fd-a8fe-3cbf7be9b61d",
"name": "Theater"
},
{
"id": "5fa1a3ce-fd5f-450f-92b7-2be6e3d0df90",
"name": "Family"
},
{
"id": "ed492986-b8a7-43c3-be3d-b17c4055bfa0",
"name": "Outdoors"
}
],
"genres": [],
"featuredImage": "https://www.daysoutguide.co.uk/media/1234/london-eye.jpg",
"images": [],
"region": "London",
My next query looks like:
var query2 = Query<Attraction>.Bool(
bq => bq.Filter(
fq => fq.Terms(t => t.Field(f => f.Region).Terms(request.Region.ToLower())),
fq => fq.Terms(t => t.Field(f => f.Categories).Terms(request.Category.ToLower())))
The query generated looks like:
{
"query": {
"bool": {
"filter": [
{
"terms": {
"region": [
"london"
]
}
},
{
"terms": {
"categories": [
"family"
]
}
}
]
}
}
}
That returns no results. If i take out the categories bit i get results. So i am trying to do term filter on categories which is an array of objects. Looks like I am doing this query wrong. Anyone any hints on how to get this to work?
Regards
Ismail
You can still use strongly typed properties access by using:
t.Field(f => f.Categories.First().Name)
NEST's property inferrer will reader will read over .First() and yield categories.name.
t.Field(f => f.Categories[0].Name) works as well.

Logstash 5.0 Ruby Filter Can't Update Hash in Array

I'm a newbie to both Logstash and Ruby, and I meet a subtle problem today.
My input JSON like the following:
{
"1": "1",
"2": "2",
"market": [
{
"id": "1",
"name": "m1"
},
{
"id": "2",
"name": "m2"
}
]
}
My filter is like the following code, and I want to set event["1"] to m1, event["2"] to m2, event["market"][0]["id"] to m1, event["market"][1]["id"] to m2:
filter {
......
ruby {
code => "
markets = event.get('market')
markets.each_index do |index|
event.set(markets[index]['id'], markets[index]['name'])
markets[index]['id'] = markets[index]['name']
end
"
}
......
}
And the output is following:
{
"1": "m1",
"2": "m2",
"market": [
{
"id": "1",
"name": "m1"
},
{
"id": "2",
"name": "m2"
}
]
}
The event["1"] and event["2"] get the expected values, but the event["market"][0]["id"] and event["market"][1]["id"] do not, and I want to know why? The desired output should be:
{
"1": "m1",
"2": "m2",
"market": [
{
"id": "m1",
"name": "m1"
},
{
"id": "m2",
"name": "m2"
}
]
}
PS: The logstash I'm using is version 5.0.
I think it is because of the new Event API introduced in the Logstash 5.0. After changing my filter to the following, I get the desired output:
filter {
......
ruby {
code => "
markets = event.get('market')
markets.each_index do |index|
event.set(markets[index]['id'], markets[index]['name'])
markets[index]['id'] = markets[index]['name']
end
event.set('market', markets) // comment: adding this setter in the filter
"
}
......
}
According to Logstash Git Issue, "Mutating a collections after setting it in the Event has an undefined behaviour".

Group array items with eloquent

I have the following eloquent query:
$extras = EventExtra::select('id', 'category', 'name', 'price', 'description', 'company')->get();
It gets some data from me from my database. What i want is for the returned data to be grouped twice, first by the category and then second by the company so that in the end i have something like this returned to the client:
[
{
"name": "donation",
"collection": [
{
"name": "sampleCompany1",
"array": [
{
"name": "extra1",
"description": "",
"value": ""
},
{
"name": "extra4",
"description": "",
"value": ""
},
{
"name": "extra6",
"description": "",
"value": ""
}
]
}
]
},
{
"name": "donation",
"collection": [
{
"name": "sampleCompany2",
"array": [
{
"name": "extra2",
"description": "",
"value": ""
},
{
"name": "extra3",
"description": "",
"value": ""
}
]
}
]
}]
I just typed the above myself so it might not be valid object array but basically it shows what i want to accomplish here.
You can use Collection to build your custom object. Something like this:
$return_data = Collect();
To add items in the collection with a property, you can use the put function.
$inner_data->put('name',$extras->name);
You can also add a collection within a collection.
To just push an existing collection in the collection, use push function
$inner_data->push($some_collection)
EDIT: Since you want a working example, see this below:
Lets say you want to create the following using collection:
{
"name": "extra1"
"description": "",
"value": ""
}
You will do something like this:
$my_collection = Collect();
$my_collection->put('name','extra1');
$my_collection->put('description','');
$my_collection->put('value','');
Now you can add this collection to another collection where you don't need a key. So lets say now it looks like this:
[
{
"name": "extra1"
"description": "",
"value": ""
},
{
"name": "extra4"
"description": "",
"value": ""
}
]
You will now do:
$my_final_collection = Collect();
foreach($my_collections as $my_collection) {
$my_final_collection->push($my_collection); // and so on in a loop
}

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

How do I access JSON array data?

I have the following array:
[ { "attributes": {
"id": "usdeur",
"code": 4
},
"name": "USD/EUR"
},
{ "attributes": {
"id": "eurgbp",
"code": 5
},
"name": "EUR/GBP"
}
]
How can I get both ids for futher processing as output?
I tried a lot but no success. My problem is I always get only one id as output:
Market.all.select.each do |market|
present market.id
end
Or:
Market.all.each{|attributes| present attributes[:id]}
which gives me only "eurgbp" as a result while I need both ids.
JSON#parse should help you with this
require 'json'
json = '[ { "attributes": {
"id": "usdeur",
"code": 4
},
"name": "USD/EUR"
},
{ "attributes": {
"id": "eurgbp",
"code": 5
},
"name": "EUR/GBP"
}]'
ids = JSON.parse(json).map{|hash| hash['attributes']['id'] }
#=> ["usdeur", "eurgbp"]
JSON#parse turns a jSON response into a Hash then just use standard Hash methods for access.
I'm going to assume that the data is JSON that you're parsing (with JSON.parse) into a Ruby Array of Hashes, which would look like this:
hashes = [ { "attributes" => { "id" => "usdeur", "code" => 4 },
"name" => "USD/EUR"
},
{ "attributes" => { "id" => "eurgbp", "code" => 5 },
"name" => "EUR/GBP"
} ]
If you wanted to get just the first "id" value, you'd do this:
first_hash = hashes[0]
first_hash_attributes = first_hash["attributes"]
p first_hash_attributes["id"]
# => "usdeur"
Or just:
p hashes[0]["attributes"]["id"]
# => "usdeur"
To get them all, you'll do this:
all_attributes = hashes.map {|hash| hash["attributes"] }
# => [ { "id" => "usdeur", "code" => 4 },
# { "id" => "eurgbp", "code" => 5 } ]
all_ids = all_attributes.map {|attrs| attrs["id"] }
# => [ "usdeur", "eurgbp" ]
Or just:
p hashes.map {|hash| hash["attributes"]["id"] }
# => [ "usdeur", "eurgbp" ]
JSON library what using Rails is very slowly...
I prefer to use:
gem 'oj'
from https://github.com/ohler55/oj
fast and simple! LET'S GO!

Resources