Reading a JSON file from Ruby (on Mac OS X) - ruby

I'm not a Ruby coder, but I do need to read a Json file and access to nodes using such a language.
I did my homework, but I'm not able to finish them because of my lack of knowledge I hope you can compensate.
Let's start with my sample Json file.
{
"app": [{
"name":"test",
"ip_address": "172.90.90.90"
}],
"mysql": [{
"server_password": "root",
"dbName":"dbname"
}],
"phpmyadmin": [{
"app_username": "root",
"app_password": "root"
}]
}
And this is the little code fragment I put together to read the file.
require 'json'
data = JSON.parse(File.read("data.json"))
Now, as long as I do something like
print data[0]
or
print data["app"]
everything is fine, but if I try to access the subnode "app"."name" no matter the format or the parenthesis I sue, I always get a system exception. I was expecting as the most reasonable way to do this something like data["app"]["name"] but it is clearly not the case.
I'm testing this using ruby compiler on a Mac Os X which, and Ruby version should be the latest as far as I can understand (ruby 2.0.0p247)
Can you please help me out?
Thanks and have an happy new year start.

The reason is because data["app"] is an array:
1.9.3p484 :001 > require 'json'
=> true
1.9.3p484 :002 > data = JSON.parse(File.read("/Users/example/Desktop/json.json"))
=> {"app"=>[{"name"=>"test", "ip_address"=>"172.90.90.90"}], "mysql"=>[{"server_password"=>"root", "dbName"=>"dbname"}], "phpmyadmin"=>[{"app_username"=>"root", "app_password"=>"root"}]}
1.9.3p484 :003 > print data["app"]
[{"name"=>"test", "ip_address"=>"172.90.90.90"}]
If you do data["app"].first["name"], you'll get what you want:
1.9.3p484 :004 > print data["app"].first["name"]
test

In your sample data, app contains an Array, so you need to access it as such:
data["app"][0]["name"]

Related

How do I append/add data to an JSON file with Ruby

So I'm trying to add info to my .json file, a first name and a last name,
from just running the script via terminal in kali linux.
I have not have had much progress I have been searching online for the past 5 hours to find a way to fix this but there has not been much progress.
Which leaves me here to post this, anyone know how to fix this error?
Error from Terminal
Traceback (most recent call last):
4: from /root/Desktop/JSON_thingy.rb:8:in `<main>'
3: from /root/Desktop/JSON_thingy.rb:8:in `open'
2: from /root/Desktop/JSON_thingy.rb:9:in `block in <main>'
1: from /usr/lib/ruby/vendor_ruby/json/common.rb:156:in `parse'
/usr/lib/ruby/vendor_ruby/json/pure/parser.rb:118:in `parse': source in not valid JSON! (JSON::ParserError)
Code
require 'json'
require 'json/pure'
json = {"first_name" => "john", "last_name" => "doe"}
initial_json = File.read('/root/Desktop/jsonDatabase.json')
File.open("/root/Desktop/jsonDatabase.json","w") do |f|
f.puts JSON.pretty_generate(JSON.parse(initial_json) << json )
end
JSON
[
{
"first_name": "albert",
"last_name": "einstein"
},
{
"first_name": "edgar",
"last_name": "poe"
}
]
Of course, simply joining two JSON strings together don't work and would result in an invalid JSON. In your example, the hash you try to add would not end up in the array but behind.
The correct way is to read the existing JSON file and parse it into a RUBY data structure and add the new hash in Ruby to the array before writing everything back to JSON.
require 'json'
filename = '/root/Desktop/jsonDatabase.json'
hash = { "first_name" => "john", "last_name" => "doe" }
array = JSON.parse(File.read(filename)
array << hash
File.open(filename, 'w') do |f|
f.write(JSON.pretty_generate(array))
end
The previous answer is cleaner and I would recommend using that.
However, the trace error clearly tells you what the problem is, this line:
/usr/lib/ruby/vendor_ruby/json/pure/parser.rb:118:in `parse':
source in not valid JSON! (JSON::ParserError)
The part of your code which has errored is this:
JSON.parse(initial_json)
So you need to first make sure the data in the file you're loading is actually valid JSON. You can either use the jsonlint ruby gem or other online linters like https://jsonlint.com/ or if you're a duck duck go user this, either of which will "beautify" your json for you.
UPDATE
If you use ruby jsonlint you may get a deprecation warning, you can safely ignore it. But it's because one of its' dependencies trollop is throwing the deprecation warning. I have opened a pull request to fix it. But it looks like it might not be maintained, last commit is almost 2 years ago. *Sigh

How can I find entries that match a certain array of values with the mongo ruby driver

I know I can find entries in mongodb that match a certain array of values natively via this command:
db.vendors.find({"somearray.property": { $in: ["value1","value2"]}})
But how can I do this with the ruby driver 'mongo' gem?
col.find("somearray.property" => ["value1","value2"])
Regards
You can do it like this:
col.find("somearray.property" => { '$in' => ["value1","value2"] })
Not sure to understand what you mean by the "ruby driver" but if you are using mongoid (which I recommend when dealing with mongodb) you can do
col.where(:'somearray.property'.in => ["val1", "val2"])
More informations here

Convert Ruby object into HTML string with awesome_print

I'm trying to prettify an Ruby object using awesome_print so I can place this string inside an email and send it off. So in terms of code, (I know this is wrong), but here's what I'm trying to achieve:
my_str = (ap error.object).to_str
# Do something with my_str, like stick it in a <pre> tag inside an html email.
How do I convert the output from ap to string? Reason I'm asking is as I noticed, ap seems to only return the object.
It doesn't seem to be documented in the README.md, but if you look at the Kernel modifications the library makes here: https://github.com/michaeldv/awesome_print/blob/master/lib/awesome_print/core_ext/kernel.rb
You can see that in addition to the ap method, the awesome_print gem also adds an ai method to all objects.
1.9.3p392 :001 > require 'awesome_print'
=> true
1.9.3p392 :002 > test = {a: "b"}
=> {:a=>"b"}
1.9.3p392 :003 > ap test
{
:a => "b"
}
1.9.3p392 :006 > test.ai
=> "{\n :a\e[0;37m => \e[0m\e[0;33m\"b\"\e[0m\n}"
1.9.3p392 :007 > test.ai(html:true)
=> "<pre>{\n <pre>:a</pre><kbd style=\"color:slategray\"> => </kbd><pre><kbd style=\"color:brown\">"b"</kbd></pre>\n}</pre>"
That said, the output formatting might not be that useful (the html version adds a ton of whitespace, and the non-html version has the weird terminal coloring characters), and being an undocumented feature, it's liable to break without warning in a minor version update.
The other thing worth noting in the kernel.rb above is that ap and ai have aliases: awesome_print and awesome_inspect.
awesomeprint is meant for printing ASCII colors and stuff, not HTML. What I'd use is pygments gem:
# gem install pygments.rb
require 'pygments'
str = <<EOT
# This is an awesome comment on my rb script
a = 2
puts a
hsh = {asdf: 1, qwer: 2, uiop: 3}
EOT
Pygments.highlight str
https://github.com/tmm1/pygments.rb

to_json in Ruby without quotes around keys

The following two lines produce the same output:
1.9.3p327 :015 > {:key=>1234}.to_json
=> "{\"key\":1234}"
1.9.3p327 :016 > {"key"=>1234}.to_json
=> "{\"key\":1234}"
Which is the following json:
{
"key" : 1234
}
How can I get it to produce "{key:1234}"?
The output you want to achieve is not JSON. It is illegal. It seems kind of obvious that the JSON library will produce JSON output not something which is not JSON.
If you want to output something which is not JSON you need to use a library which is not JSON. In this particular case, it looks like you made up the output format, so you'll probably have to write the library yourself.
The other poster is correct about it not being valid JSON. I just wanted to copy a ruby object from my console into my code using colons instead of hash rockets
In this context you can use: https://github.com/awesome-print/awesome_print
ap({key: 1234}, ruby19_syntax: true, index: false)

Ruby: Can't save document with Libxml-ruby

From the libxml-ruby API docs (http://libxml.rubyforge.org/rdoc/index.html), under LibXML::XML::Document, I tried the following:
filename = 'something.xml'
stats_doc = XML::Document.new()
stats_doc.root = XML::Node.new('root_node')
stats_doc.root << XML::Node.new('elem1')
stats_doc.save(filename, :indent => true, :encoding => 'utf-8')
... which resulted in this error:
parse_stats.rb:26:in `save': can't convert String into Integer (TypeError)
(where the last line in the block above was line 26).
I tried changing the file name to an integer, which gave me this:
parse_stats.rb:26:in `save': wrong argument type Fixnum (expected String) (TypeError)
So I gathered that I need to use a string, but strings don't seem to work. Since I seem to be unable to find any examples of libxml-ruby in action off Google, I'm at a loss. Any help would be very appreciated, or links to any online example where I can see how libxml-ruby is used for creating XML documents.
libxml-ruby 1.1.3
rubygems 1.3.1
ruby 1.8.7
Seems that the problem is with encoding. Try XML::Encoding::UTF_8 instead of "utf-8".
require 'rubygems'
require 'libxml'
filename = 'something.xml'
stats_doc = LibXML::XML::Document.new()
stats_doc.root = LibXML::XML::Node.new('root_node')
stats_doc.root << LibXML::XML::Node.new('elem1')
stats_doc.save(filename, :indent => true, :encoding => LibXML::XML::Encoding::UTF_8)

Resources