Trouble parsing file obtained from Dir.glob - json

I am new to ruby. Running into error while trying to parse file obtained from Dir.glob command using JSON.parse()
require 'json'
Dir.glob('**/*/.json').each do |f| # find all the .json file and loop each file
puts f
data = JSON.parse(f)
if data['Apple'].nil?
puts "skipping file #{f} as it does not have Apple"
next
end
parsed_key= File.dirname(data['Apple'][0]['red'][0]['key'])
puts parsed_key
end
`parse': 767: unexpected token at 'xyz/abc/config.json' (JSON::ParserError)

f there is just the path, a String. If you want the contents of the file you'll need to read it first, data = JSON.parse(File.read(f))

Related

Writing to a .json file

I am currently trying to write 2 pieces of user inputted code to a .json file without clearing the existing data. I believe it is a problem with the logins.append as it says there is no such thing. What would i have to use?
I have been searching around trying to find different suffixes to the logins.
def i():
path_to_json = "./logins.json"
with open("logins.json", "r") as content:
logins = json.load(content)
with open('logins.json', 'a') as outfile:
username = str(input('New Username: '))
password = str(input('New Password: '))
logins.append({username:password})
I am getting the error:
Traceback (most recent call last):
File "<pyshell#5>", line 1, in <module>
i()
File "N:\NEA Computing\NEA code.py", line 188, in i
logins.append({username: password})
AttributeError: 'dict' object has no attribute 'append'
I am expecting it to add data to the .json file without deleting the other data however i am getting an error and nothing is being written to the .json file.
Try to open the file with 'w' option
def i():
path_to_json = "./logins.json"
with open("logins.json", "w") as content:
logins = json.load(content)
with open('logins.json', 'a') as outfile:
username = str(input('New Username: '))
password = str(input('New Password: '))
logins.append({username:password})
Maybe this is a misunderstanding of the question, but what is happening, as far as I can see, is that you use json.load, which seems to load an object literal like {key1: value1, key2: value2,...} and not an array literal like [value1, value2, ...]. Python converts the first one into a python dict, and a dictionary has no append function, only an array / a list has. You get your error and execution halts. When you have the content of logins.json as object {...}, it doesn't work for me but as array/list [...] it works

Ruby: Handling different JSON response that is not what is expected

Searched online and read through the documents, but have not been able to find an answer. I am fairly new and part of learning Ruby I wanted to make the script below.
The Script essentially does a Carrier Lookup on a list of numbers that are provided through a CSV file. The CSV file has just one row with the column header "number".
Everything runs fine UNTIL the API gives me an output that is different from the others. In this example, it tells me that one of the numbers in my file is not a valid US number. This then causes my script to stop running.
I am looking to see if there is a way to either ignore it (I read about Begin and End, but was not able to get it to work) or ideally either create a separate file with those errors or just put the data into the main file.
Any help would be much appreciated. Thank you.
Ruby Code:
require 'csv'
require 'uri'
require 'net/http'
require 'json'
number = 0
CSV.foreach('data1.csv',headers: true) do |row|
number = row['number'].to_i
uri = URI("https://api.message360.com/api/v3/carrier/lookup.json?PhoneNumber=#{number}")
req = Net::HTTP::Post.new(uri)
req.basic_auth 'XXX' , 'XXX'
res = Net::HTTP.start(uri.hostname, uri.port, :use_ssl => true) {|http|
http.request(req)
}
json = JSON.parse(res.body)
new = json["Message360"]["Carrier"].values
CSV.open("new.csv", "ab") do |csv|
csv << new
end
end
File Data:
number
5556667777
9998887777
Good Response example in JSON:
{"Message360"=>{"ResponseStatus"=>1, "Carrier"=>{"ApiVersion"=>"3", "CarrierSid"=>"XXX", "AccountSid"=>"XXX", "PhoneNumber"=>"+19495554444", "Network"=>"Cellco Partnership dba Verizon Wireless - CA", "Wireless"=>"true", "ZipCode"=>"92604", "City"=>"Irvine", "Price"=>0.0003, "Status"=>"success", "DateCreated"=>"2018-05-15 23:05:15"}}}
The response that causes Script to stop:
{
"Message360": {
"ResponseStatus": 0,
"Errors": {
"Error": [
{
"Code": "ER-M360-CAR-111",
"Message": "Allowed Only Valid E164 North American Numbers.",
"MoreInfo": []
}
]
}
}
}
It would appear you can just check json["Message360"]["ResponseStatus"] first for a 0 or 1 to indicate failure or success.
I'd probably add a rescue to help catch any other errors (malformed JSON, network issue, etc.)
CSV.foreach('data1.csv',headers: true) do |row|
number = row['number'].to_i
...
json = JSON.parse(res.body)
if json["Message360"]["ResponseStatus"] == 1
new = json["Message360"]["Carrier"].values
CSV.open("new.csv", "ab") do |csv|
csv << new
end
else
# handle bad response
end
rescue StandardError => e
# request failed for some reason, log e and the number?
end

ruby sketchup scene serialization

I am very new on Sketchup and ruby , I have worked with java and c# but this is the first time with ruby.
Now I have one problem, I need to serialize all scene in one json (scene hierarchy, object name, object material and position this for single object) how can I do this?
I have already done this for unity3D (c#) without a problem.
I tried this:
def main
avr_entities = Sketchup.active_model.entities # all objects
ambiens_dictionary = {}
ambiens_list = []
avr_entities.each do |root|
if root.is_a?(Sketchup::Group) || root.is_a?(Sketchup::ComponentInstance)
if root.name == ""
UI.messagebox("this is a group #{root.definition.name}")
if root.entities.count > 0
root.entities.each do |leaf|
if leaf.is_a?(Sketchup::Group) || leaf.is_a?(Sketchup::ComponentInstance)
UI.messagebox("this is a leaf #{leaf.definition.name}")
end
end
end
else
# UI.messagebox("this is a leaf #{root.name}")
end
end
end
end
Have you tried the JSON library
require 'json'
source = { a: [ { b: "hello" }, 1, "world" ], c: 'hi' }.to_json
source.to_json # => "{\"a\":[{\"b\":\"hello\"},1,\"world\"],\"c\":\"hi\"}"
Used the code below to answer a question Here, but it might also work here.
The code can run outside of SketchUp for testing in the terminal. Just make sure to follow these steps...
Copy the code below and paste it on a ruby file (example: file.rb)
Run the script in terminal ruby file.rb.
The script will write data to JSON file and also read the content of JSON file.
The path to the JSON file is relative to the ruby file created in step one. If the script can't find the path it will create the JSON file for you.
module DeveloperName
module PluginName
require 'json'
require 'fileutils'
class Main
def initialize
path = File.dirname(__FILE__)
#json = File.join(path, 'file.json')
#content = { 'hello' => 'hello world' }.to_json
json_create(#content)
json_read(#json)
end
def json_create(content)
File.open(#json, 'w') { |f| f.write(content) }
end
def json_read(json)
if File.exist?(json)
file = File.read(json)
data_hash = JSON.parse(file)
puts "Json content: #{data_hash}"
else
msg = 'JSON file not found'
UI.messagebox(msg, MB_OK)
end
end
# # #
end
DeveloperName::PluginName::Main.new
end
end

JSON to Hash in Ruby and vice-versa using Files - Parser Error

I am trying to save data from a Hash to a file. I convert it to JSON and dump it into the file.
When I try to parse back from file to hash I get JSON::ParserError
Code to convert Hash to JSON file: (works fine)
user = {:email => "cumber#cc.cc", :passwrd => "hardPASSw0r|)"}
student_file = File.open("students.txt", "a+") do |f|
f.write JSON.dump(user)
end
After adding a few values one by one to the file it looks something like this:
{"email":"test1#gmail.com","passwrd":"qwert123"}{"email":"test3#gmail.com","passwrd":"qwert12345"}{"email":"cumber#cc.cc","passwrd":"hardPASSw0r|)"}
I tried the following code to convert back to Hash but it doesn't work:
file = File.read('students.txt')
data_hash = JSON.parse(file)
I get
System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/json/common.rb:155:in `parse': 757: unexpected token at '{"email":"test3#gmail.com","passwrd":"qwert12345"}{"email":"cumber#cc.cc","passwrd":"hardPASSw0r|)"}' (JSON::ParserError)
from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/json/common.rb:155:in `parse'
from hash_json.rb:25:in `<main>'
My goal is to be able to add and remove values from the file.
How do I fix this, where was my mistake? Thank you.
This should work:
https://repl.it/EXGl/0
# as adviced by #EricDuminil, on some envs you need to include 'json' too
require 'json'
user = {:email => "cumber#cc.cc", :passwrd => "hardPASSw0r|)"}
student_file = File.open("students.txt", "w") do |f|
f.write(user.to_json)
end
file = File.read('students.txt')
puts "saved content is: #{JSON.parse(file)}"
p.s. hope that this is only an example, never store passwords in plain-text! NEVER ;-)

Rails: Creating a csv file in a rake task - can't access a classes database column_names

I am struggling to create a simple rake task which will generate a csv dump of the database table "baselines".
task :send_report => :environment do
path = "tmp/"
filename = 'data_' + Date.today.to_s + '.csv'
Baseline.all.each do
CSV.open(path + filename, "wb") do |csv|
csv << Baseline.column_names
Baseline.all.each do |p|
csv << p.attributes.values_at(*column_names)
end
end
end
end
I am getting the error
undefined local variable or method `column_names' for main:Object
I am completely unclear why this is....Baseline.column_names will work in the console, in a view etc etc.
Any thought would be appreciated.
You're specifying Baseline.column_names in the first case, but just column_names on your values_at call. That defaults to the main context where no such method exists. It must be called against a model.
Make those two consistent, Baseline is required in both cases.