JSON serializing and deserializing with special characters with RAILS - ruby-on-rails

I really feel a bit stupid as to what to do to make this simple line work, I looked around, and no answer seemed to really answer this, can anyone can tell me how to serialize and deserialize something as simple as that:
JSON.parse("É".to_json)
JSON::ParserError: 757: unexpected token at '"\u00e9"'
EDIT:
The real problem was more akin to saving a hash in the database with a é in the string, like this:
{"Hu00c9MO":"JOUR"}
It seems the string is not good, and I can't bring back the é after decoding from JSON

I think the problem is not the "É". I just tried this:
JSON.parse("A".to_json)
JSON::ParserError: 757: unexpected token at '"A"'
And as you can see it throws the same type of error.
The problem here is that a single string as "É" is not a valid JSON, and even though you can use to_json to serialize it, when you try to parse it, it will hang. Try this for example:
JSON.parse({'key' => 'É'}.to_json)
As stated in the docs:
JSON.generate only allows objects or arrays to be converted to JSON
syntax. to_json, however, accepts many Ruby classes even though it
acts only as a method for serialization
(.to_json is just an alternative to JSON.generate)

Accord http://www.json.org/ JSON should be an object {id: value} or an array [value1, value2].
You are passing to parse only a value. Try something like: JSON.parse(["É"].to_json) or JSON.parse({value: "É"}.to_json)
EDIT As Question was Edited:
Accord http://www.json.org When JSON is on object {id: value}, id can be Any UNICODE charecter except " or \ or control charecter This is the reason why you can't get back "É" in the id side.
Maybe the solution is replace "\" with another valid character before save into DB and do the reverse replace when you read it from DB or just escape "\" with "\".

Related

response checksum or hash not matching in payumoney?

When notification is passed to the app after payumoney processing it sends response hash and we need to compute the hash and match it with the passed in response hash.
I use the following code to compute the expected response hash.
Digest::SHA512.hexdigest([
PAYU_SALT,
notification.transaction_status,
notification.user_defined,
notification.customer_email,
notification.customer_first_name,
notification.product_info,
notification.gross,
notification.invoice,
PAYU_KEY].join("|"))
The hash of the following string is computed
"salt|success|||||||||||||Payment|100.0|1|key"
When I print the following hash it gives
Digest::SHA512.hexdigest([
PAYU_SALT,
notification.transaction_status,
notification.user_defined,
notification.customer_email,
notification.customer_first_name,
notification.product_info,
notification.gross,
notification.invoice,
PAYU_KEY].join("|"))
#⇒ e7b3c5ba00b98aad9186a5e6eea65028a[...]
whereas notification.checksum gives
#⇒ 546f5d23e0cadad2d4158911ef72f095d[...]
So the two hashes don’t match.
I am using the following gem: https://github.com/payu-india/payuindia
I appreciate any help as to why the response hash is not matching. Is there any error in my logic to compute the response hash? Thanks!
Where did you come up with that order for the fields in the array?
Looking at PayU's Developer FAQ it seems like the order is the following:
key|txnid|amount|productinfo|firstname|email|||||||||||salt
Please make sure that the hash is calculated in the following format - hashSequence= key|txnid|amount|productinfo|firstname|email|udf1|udf2|udf3|udf4|udf5||||||salt
Please make sure that in the above sequence please use the UDFs which have also been posted to our server. In case you haven't posted any UDFs, the hash sequence should look like this - hashSequence= key|txnid|amount|productinfo|firstname|email|||||||||||salt.
Keep in mind that when computing the hash even a single character out of place will result in a completely different checksum.
little late but Actual Sequence is:
SALT|status||||||udf5|udf4|udf3|udf2|udf1|email|firstname|productinfo|amount|txnid|key
Thanks to Ravi Kant Singh
but additionalCharges| are removed
Tested with live environment
Check your hash in above order and if its match you can process request
ok this was a silly mistake i made. The reason the hash didn't match was beacuse i had a typo with the PAYU test key. At the end i typed small 'u' when it was 'U'. The library is fine and the logic is right. The error was in my side with using wrong key.
Actual Sequence for hash is :
additionalCharges|SALT|status||||||udf5|udf4|udf3|udf2|udf1|email|firstname|productinfo|amount|txnid|key
Actual hash generation for additional charges:
additionalCharges|SALT|status||||||udf5|udf4|udf3|udf2|udf1|email|firstname|productinfo|amount|txnid|key
Without additional charges:
SALT|status||||||udf5|udf4|udf3|udf2|udf1|email|firstname|productinfo|amount|txnid|key

Rails: parse weirdly-formatted JSON

My JSON response from an external service looks like this:
Parameters: {"{\"attributes\":{\"type\":\"Lead\",\"url\":\"/services/lead/2231\"},\"Id\":\"2231\",\"FirstName\":\"Jean\"}"=>nil, "external_id"=>"2231"}
How can I parse the Id and FirstName keys in Rails 5? I've tried everything. I know Rails 5 has the .to_unsafe_h method, that's not my problem. It's more the weird nested formatting that has a value of nil after "Jean" above.
If you pay attention closely, you will see:
"{\"attributes\":{\"type\":\"Lead\",\"url\":\"/services/lead/2231\"},\"Id\":\"2231\",\"FirstName\":\"Jean\"}" is actually a string, a key, and the value value associated to it is nil.
If you want to parse that, just can use parameters.keys[0].to_json; although I will double check first why you are getting the parameters in that incorrect state in the first place.

How to format a text area sent as an array via JSON?

I'm pretty new to Ruby, and I'm using it work with an API. Text area's sent over the API are converted to the format below before being sent to me via a JSON POST request:
"Comment": [
"hdfdhgdfgdfg\r",
"This is just a test\r",
"Thanks!\r",
"- Kyle"
]
And I'm getting the value like this:
comments = params["Comment"]
So each line is broken down into what looks like an array. My issue is, it functions just like one big string instead of an array with 4 values. I tried using comments[0] and just printing comments but both return the same result, it just displays everything as a string, ie
["hdfdhgdfgdfg\r", "This is just a test\r", "Thanks!\r", "- Kyle"]
But I need to display it as it appears in the text area, ie
hdfdhgdfgdfg
This is just a test
Thanks!
- Kyle
I know I could just strip out all the extra characters, but I feel like there has to be a better way. Is there a good way to convert this back to the original format of a text area, or at least to convert it to an array so I can loop through each item and re-format it?
First, get rid of those ugly \rs:
comments.map!(&:chomp)
Then, join the lines together:
comment = comments.join("\n") # using a newline
# OR, for HTML output:
comment = comments.join('<br>')
You should be able to parse the JSON and populate a hash with all of the values:
require 'json'
hash = JSON.parse(params["Comment"])
puts hash
=> {"Comment"=>['all', 'of', 'your', 'values']}
This should work for all valid json. One of the rules of json syntax is that
Data is in name/value pairs
The json you provided doesn't supply names for the values, therefore this method might not work. If this is the case, parsing the raw string and extracting values would do the job as well (although more messy).
How you might go about doing that:
json = params["Comment"]
newArray = []
json.split(" ").each do |element|
if element.length > 1
newArray << element
end
end
This would at least give you an array with all of your values.

How to remove backslashes in string generated through .to_json function. Rails 3.2

["{\"id\":317277848652099585,\"Tweet text\":\"Food Carnival by KMS Homemade Food\\nOn the occasion of this Holi and Good Friday, KMS Homemade Foods invites you... http://t.co/2Y2mO6vr76\",\"Word count\":21,\"Url\":\"true\"}"]
a is a hash with some keys and values.
a = a.to_json
converts the hash to a string.
Now a is a string with all backslashes...
I know tha
puts a
returns a string with all backslashes removed but what if i want to store the 'backslash removed string' in a variable?
It's much better to use as_json instead. Provides the json without backslashes.
For reference,
http://api.rubyonrails.org/classes/ActiveModel/Serializers/JSON.html
You can just gsub! to replace the \" with a single quote ', like so:
a.gsub!(/\"/, '\'')
I faced the same problem and I did eval(a) and it gave me actual hash with no double quotes and slashes although eval is considered security risk

Clean up & style characters from text

I am getting text from a feed that has alot of characters like:
Insignia&#153; 2.0 Stereo Computer Speaker System (2-Piece) - Black
4th-Generation Apple® iPod® touch
Is there an easy way to get rid of these, or do I have to anticipate which characters I want to delete and use the delete method to remove them? Also, when I try to remove
&
with
str.delete("&")
It leaves behind "amp;" Is there a better way to delete this type of character? Do I need to re-encode the text?
String#delete is certainly not what you want, as it works on characters, not the string as a whole.
Try
str.gsub /&/, ""
You may also want to try replacing the & with a literal ampersand, such as:
str.gsub /&/, "&"
If this is closer to what you really want, you may get the best results unescaping the HTML string. If so try this:
CGI::unescapeHTML(str)
Details of the unescapeHTML method are here.
If you are getting data from a 'feed', aka RSS XML, then you should be using an XML parser like Nokogiri to process the XML. This will automatically unescape HTML entities and allow you to get the proper string representation directly.
For removing try to use gsub method, something like this:
text = "foo&bar"
text.gsub /\b&\b/, "" #=> foobar

Resources