formatting JSON object in rails 3 - ruby-on-rails

I have a rails app has an api for iphone/android clients. I'm doing Message.find(1).to_json(:include => :user) but that adds \ around " to escape it.
How can I prevent to_json from escaping the double quotes?
>> { "a" => "blah" }.to_json
=> "{\"a\":\"blah\"}"
I would like it to be { "a" : "blah" } or { a : "blah" }

It looks like this is actually what you want.
What you are seeing is the string formatted for display (and human readability). It is delimited by double quotes, so the double quotes inside the string are escaped. In reality, the string contains double quotes, but for literal representation, they are escaped. If you stick this into a JSON parser you will find it returns the object you want.
If you were to print this out, you will find that you get the format you want.
irb(main):001:0> puts { "a" => "blah" }.to_json
{"a":"blah"}
=> nil
For further illustration, you could try parsing it. The string you ended up with returns your original object, because JSON is represented by a string. However, attempting to insert the desired content will give you a nasty syntax error or a TypeError. This is because JSON is not a literal in Ruby, whereas in JavaScript it can be used as a literal object. In Ruby it is a representation in the form of a string.
irb(main):002:0> JSON.parse("{\"a\":\"blah\"}")
=> {"a"=>"blah"}
irb(main):003:0> JSON.parse({ "a" : "blah" })
SyntaxError: (irb):3: syntax error, unexpected ':', expecting tASSOC
JSON.parse({ "a" : "blah" })
^
(irb):3: syntax error, unexpected '}', expecting $end
JSON.parse({ "a" : "blah" })
^
irb(main):004:0> JSON.parse({a:"blah"})
TypeError: can't convert Hash into String

Related

setting conditional attributes for API connection

A method needs to instantiate a session with various attributes, some of which are optional
session = Checkout::Session.create({
locale: I18n.locale,
reference_id: id,
customer_email: #user_mail,
[...]
})
The last shown attribute, customer_email, is optional but it should not be generated if the value does not exist.
customer_email: #user_mail unless !#user_email,
logically hits a syntax error because an additional param (the comma) is being produced
syntax error, unexpected ',', expecting end
and thus the API expects another attribute.
(customer_email: #user_mail, unless !#user_email)
also fails as there is confusion over the parenthesis
syntax error, unexpected ')', expecting then or ';' or '\n'
How should this syntax be cast?
You need to extract the options hash into a variable and manipulate it before sending it to the Checkout::Session.create.
Something like this:
options = {
locale: I18n.locale,
reference_id: id
}
options[:customer_email] = #user_mail if #user_email
session = Checkout::Session.create(options)

how to parse JSON with single and double quotes in ruby on rails

I am Having an issue where if a name comes in with a ' or " my JSON parsing fails. I want to know how i can avoid this.
This is my current code:
def create
puts params
##contact = Contact.new(contact_params)
##contact.user = current_user
contactsParam = params[:contacts]
if contactsParam
# contactsParam.each do |contact|
# end
contactValues = contactsParam.map { |c|
puts "dulce!!! : " + c.to_s
json = JSON.parse(c)
result = "('#{json['name']}', '#{json['phone_number']}', '#{json['detail']}', '#{json['image_url']}', '#{json['email']}', '#{json['address']}', '#{json['city']}', '#{json['state']}', '#{json['zipcode']}', '#{json['country']}', #{current_user.id}, now(), now())"
result
}.join(",")
if contactValues.length > 0
ActiveRecord::Base.connection.execute("INSERT INTO contacts (name, phone_number, detail, image_url, email, address, city, state, zipcode, country, user_id, created_at, updated_at) VALUES #{contactValues}")
end
end
here is an example of a JSON String that fails (i added a bunch of random characters to test).
{"name":"Aaacontacttest'/'#"-jgg&$;$/&/#.'sheh","phone_number":",7*#;878545848487849648","detail":"","image_url":"","email":"test#test.com","address":"-/:;()$#""":$;$:$$/!:!/!,!6677bhgv
2017-07-25T20:08:54.614283+00:00 app[web.1]: Hsbsbsbb7788$!","city":"Hehshdbdb","state":"HSSHHSHS$&:$:$","zipcode":"3319)","country":"United States"}
1.
Let's first correct the JSON Object which you gave:
{
"name":"Aaacontacttest'/'#"-jgg&$;$/&/#.'sheh",
"phone_number":",7*#;878545848487849648",
"detail":"",
"image_url":"",
"email":"test#test.com",
"address":"-/:;()$#""":$;$:$$/!:!/!,!6677bhgv2017-07-25T20:08:54.614283+00:00 app[web.1]: Hsbsbsbb7788$!",
"city":"Hehshdbdb",
"state":"HSSHHSHS$&:$:$",
"zipcode":"3319)",
"country":"United States"
}
The problem with this JSON object is, it is not closed properly. If you wanted to use quotes in your object then please use Backslash to omit to close the value of the object.
Let's convert the above invalid JSON Object to valid JSON object first, such ruby avoid syntax error:
{
"name":"Aaacontacttest'/'#\"-jgg&$;$/&/#.'sheh",
"phone_number":",7*#;878545848487849648",
"detail":"",
"image_url":"",
"email":"test#test.com",
"address":"-/:;()$#\"\"\":$;$:$$/!:!/!,!6677bhgv2017-07-25T20:08:54.614283+00:00 app[web.1]: Hsbsbsbb7788$!",
"city":"Hehshdbdb",
"state":"HSSHHSHS$&:$:$",
"zipcode":"3319)",
"country":"United States"
}
What we did over here:
Initial Hash object with the "name" as the key has a value:
"name":"Aaacontacttest'/'#"-jgg&$;$/&/#.'sheh"
Area with bold depicting that you have closed the value with quotes where rest of the Italic character is marked as invalid.
Types of errors which ruby would be raised either "syntax error" or unexpected 'any char', expecting end-of-input
We have introduced backslash in the value to ensure proper closing of the value.
"name":"Aaacontacttest'/'#\"-jgg&$;$/&/#.'sheh"
So where ever you have used quotes in your value please omit them using backslash.
The object which you gave is the normal hash object not a JSON object in case of ruby, as Ruby JSON parser expects the argument to be a string and can’t convert objects like a hash or array.
If you do JSON.generate(hash) you will get the JSON object:
Note: hash if the corrected hashobject.
Adding JSON object over here.
"{\"name\":\"Aaacontacttest'/'#\\"-jgg&$;$/&/#.'sheh\",\"phone_number\":\",7*#;878545848487849648\",\"detail\":\"\",\"image_url\":\"\",\"email\":\"test#test.com\",\"address\":\"-/:;()$#\\"\\"\\":$;$:$$/!:!/!,!6677bhgv2017-07-25T20:08:54.614283+00:00 app[web.1]: Hsbsbsbb7788$!\",\"city\":\"Hehshdbdb\",\"state\":\"HSSHHSHS$&:$:$\",\"zipcode\":\"3319)\",\"country\":\"United States\"}"
If you do JSON.parse(HashObject not JSONobject) the ruby would throw an error:
TypeError: no implicit conversion of Hash into String
Summary:
Correct your hashObject.
Convert you hashObject into the valid JSON object for ruby. If you wanted to generate JSON use JSON.generate(hash) method.

How to check if a string contain valid hash

i encounter a problem when i want to validate the input string if it contain a valid hash before execute eval on it, for example:
"{:key=>true}" if i run eval it return a correct hash, but if i run eval on this string "{:key=>true" i get syntax error of expected token:
(eval):1: syntax error, unexpected end-of-input, expecting '}' {:redirect=>true ^
i did tried some basic validation but no luck so far.
so basically what i want to know is how to validate a that a string contain correct hash format.
You can't tell without actually parsing it as Ruby, and (assuming you trust the string), the simplest way of parsing it is to simply do the eval call, and handle the exception:
begin
hash = eval(string)
rescue SyntaxError
# It's not valid
end
This is precisely what exceptions are for, instead of littering your code with checks for whether operations will succeed, you just perform the operations, and handle errors that occur.
To validate the string you can use Kernel#eval + checking the type:
def valid_hash?(string)
eval(string).is_a?(Hash)
rescue SyntaxError
false
end
Usage:
string = "{:key=>true}"
valid_hash?(string)
#=> true
string = "I am not hash"
valid_hash?(string)
#=> false
I had a similar problem, but I don't like the eval solution, because it's not safe.
I used the JSON gem and modified the string to match the JSON syntax.
Assuming you only have symbol keys.
'key: value' to '"key": value'
':key => value' to '"key": value'
string1 = "{:key_1=>true,key_2:false}"
string2 = "{:key=>true}"
string3 = "no hash"
def valid_hash?(string)
begin
string = string.gsub(/(\w+):\s*([^},])/, '"\1":\2')
#=> "{:key_1=>true,\"key_2\":false}"
string = string.gsub(/:(\w+)\s*=>/, '"\1":')
#=> "{\"key_1\":true,\"key_2\":false}"
my_hash = JSON.parse(string, {symbolize_names: true})
#=> {:key_1=>true, :key_2=>false}
my_hash.is_a? Hash # or do whatever you want with your Hash
rescue JSON::ParserError
false
end
end
valid_hash? string1
#=> true
valid_hash? string2
#=> true
valid_hash? string3
#=> false

Convert JSON string to hash

I have a Ruby on Rails JSON question.
I have what I think is a strange error. I have the following JSON string which I get like this from an external API
test = "[{'domain': 'abc.com'}, {'domain': 'def.com'}, {'domain': 'ghi.com'}]"
Now, I want to convert this string to a hash using:
hash = JSON.parse test
The problem is that it errors with:
JSON::ParserError: 419: unexpected token at '{'domain': 'abc.com'}, {'domain': 'def.com'}, {'domain': 'ghi.com'}]'
The problem now with just replacing ' with " is dangerous if any strings includes ' or ". Anyone have a solution?
It's most likely because this isn't valid JSON. Change your single quotes to double quotes, like so:
test = '[{"domain": "abc.com"}, {"domain": "def.com"}, {"domain": "ghi.com"}]'
An explanation can be found here, and you can validate your JSON here.
You're getting an error because your string isn't valid JSON. In JSON all property names must be double-quoted and string values must also be double-quotes. Single-quotes are never valid.
test = '[{"domain": "abc.com"}, {"domain": "def.com"}, {"domain": "ghi.com"}]'
JSON.parse(test)
# => [ { "domain" => "abc.com" },
# { "domain" => "def.com" },
# { "domain" => "ghi.com" } ]
Using Rails 4 or above, If you want to have symbol keys instead of string keys, you can use deep_symbolize_keys method
hash = JSON.parse(test).deep_symbolize_keys
That's in addition that the real problem was invalid json as MyCah mentioned.
Use this piece of code. you are missing ActiveSupport::JSON
ActiveSupport::JSON.decode json_string

factorygirl order of parameters break create() method?

Why does:
fi = FactoryGirl.create(:finder_item, store_id: s.id, :category_foo, :random_question)
throw an error finder_item_spec.rb:20: syntax error, unexpected ',', expecting tASSOC (SyntaxError)
but simply re-ordering so the the traits are before the assignment works fine:
fi = FactoryGirl.create(:finder_item, :category_foo, :random_question, store_id: s.id)
One of your arguments is not just symbol type - it's :key => value, and for a FG order of arguments with different types is something that matters.

Resources