Ruby / Sinatra JSON.parse is failing - ruby-on-rails

the String that I'm trying to parse is:
{\"user_name\":\"test#test.com\",\"pass\":\"bla\"}
[3] pry(#<Flockers::WebApp>)> JSON.parse(request.body.read)
JSON::ParserError: A JSON text must at least contain two octets!
from c:/WebTools/Ruby193/lib/ruby/gems/1.9.1/gems/json_pure-1.8.1/lib/json/commo
n.rb:155:in `initialize'
When I execute JSON.parse in javascript, this works, but this is not parsing properly in ruby console.

This error can be caused by passing JSON.parse an empty string. Try running request.body.rewind before request.body.read.

Related

Rails loading ActiveSupport regex with ISO-8859-1 encoding instead of UTF-8

When I call '返回'.titleize on a Chinese-language string in the Rails 6 app on my server, I get an error:
Encoding::CompatibilityError: incompatible encoding regexp match (ISO-8859-1 regexp with UTF-8 string)
The source for the titleize function leads to the following in ActiveSupport::Inflector:
def titleize(word, keep_id_suffix: false)
humanize(underscore(word), keep_id_suffix: keep_id_suffix).gsub(/\b(?<!\w['’`()])[a-z]/) do |match|
match.capitalize
end
end
Although calling ActiveSupport::Inflector.titleize('返回') gives the error above, if I just copy the function body and run it as follows, there's no error --- I just get the correct titleize behaviour:
ActiveSupport::Inflector.humanize(ActiveSupport::Inflector.underscore('返回'), keep_id_suffix: false).gsub(/\b(?<!\w['’`()])[a-z]/) do |match|
match.capitalize
end
I guess that the regular expression /\b(?<!\w['’()])[a-z]/ is getting compiled with a ISO-8859-1 encoding when ActiveSupport::Inflector loads but is compiling with a different encoding when I run it in my Rails console, but I don't see anything I can do with this information.
What can I do to get the Rails helper titleize to work on my server as intended?
I'm on Rails 6, Ruby 2.6.6, and ENV["LANG"] is en_US.utf8.

Rails: mongodb error when using $lt

this code return an error
db[:zips].find(city: {$lt: 'd'}).limit(2).to_a.each{|r| pp r}
syntax error, unexpected '}', expecting end-of-input
However, this code works well
db[:zips].find(city: {:$lt=> 'd'}).limit(2).to_a.each{|r| pp r}
Why can not use :$lt like the first one?
You can't use the JSON-like {key: value} syntax in this case , because the key starts with $. Either use the older hash syntax or, since ruby 2.2,
{'$lt': 'd'}
I couldn't find a reference for when quoting is required (emojis are OK for example) - I suspect you would have to delve into the ruby source for this.

JSON encoding/decoding with unicode in rails

I upgraded downgraded to rails 2.3.17 due to the security bugs, but now I can't decode json strings that I have saved down to a DB if they have unicode in them :(. Is there a way to process the string such that it decodes properly?
e = ActiveSupport::JSON.encode({'a' => "Hello Unicode \u2019"})
ActiveSupport::JSON.decode(e)
gives me
RangeError: 8217 out of char range
from /app/vendor/bundle/ruby/1.9.1/gems/activesupport-2.3.17/lib/active_support/json/backends/okjson.rb:314:in `unquote'
from /app/vendor/bundle/ruby/1.9.1/gems/activesupport-2.3.17/lib/active_support/json/backends/okjson.rb:251:in `strtok'
from /app/vendor/bundle/ruby/1.9.1/gems/activesupport-2.3.17/lib/active_support/json/backends/okjson.rb:215:in `tok'
from /app/vendor/bundle/ruby/1.9.1/gems/activesupport-2.3.17/lib/active_support/json/backends/okjson.rb:178:in `lex'
from /app/vendor/bundle/ruby/1.9.1/gems/activesupport-2.3.17/lib/active_support/json/backends/okjson.rb:46:in `decode'
from /app/vendor/bundle/ruby/1.9.1/gems/activesupport-2.3.17/lib/active_support/json/backends/okjson.rb:612:in `decode'
from /app/vendor/bundle/ruby/1.9.1/gems/activesupport-2.3.17/lib/active_support/json/decoding.rb:14:in `decode'
from (irb):30
from /usr/local/bin/irb:12:in `<main>'
I can't change the first line since it's coming from the DB like that.
This used to work.
You can change the backend JSON provider in ActiveSupport.
Add ActiveSupport::JSON.backend = "JSONGem" into an application initialiser (I added it to application.rb). This fixed the unicode parsing issues I had after I upgraded activesupport to 3.0.20.
See the vulnerability notice which caused this update - It mentions that this workaround should apply to 2.3.16 as well.
From rails console:
> ActiveSupport::VERSION::STRING
=> "3.0.20"
> ActiveSupport::JSON.decode('{"test":"string\u2019"}')
RangeError: 8217 out of char range
> ActiveSupport::JSON.backend = "JSONGem"
> ActiveSupport::JSON.decode('{"test":"string\u2019"}')
 => {"test"=>"string’"}
The JSON gem will handle this correctly.
As a note, the gem is much more strict than the other JSON parsers out there. For example:
{ 'test' : 'value' }
This is not valid JSON even though it looks okay.
For whatever reason the non-UTF-8 savvy JSON parser shipped as part of the 2.3.16 patch which is really sloppy on the part of the maintainer.
Switch to 2.3.15 which should be fine because that's when the fixes landed.
Curse the developer who started this project in rails
Begin work on porting to python post haste

Why is my JSON.parse failing? Ruby on Rails

I'm trying to load images from Flickr's API into a Ruby on Rails app, but I'm getting "Unexpected Token" on my JSON.parse() line.
I found another response here where the returned JSON had it's double quotes escaped out, and the solution was to add the .gsub thing to the end, but I'm still getting an error.
Anyone know what the problem is?
def add
#jsonresults = open("http://api.flickr.com/services/rest/?method=flickr.interestingness.getList&api_key=bb398c11934abb6d51bdd720020f6a4a&per_page=1&page=1&format=json&nojsoncallback=1").read
#images = JSON.parse(#jsonresults.to_json.gsub('\"', '"'))
end
The error:
JSON::ParserError in ImagesController#add
757: unexpected token at '"{"photos":{"page":1, "pages":500, "perpage":1, "total":500, "photo":[{"id":"8234011021", "owner":"24066605#N07", "secret":"b4c05df8c5", "server":"8341", "farm":9, "title":"Crescent Lake", "ispublic":1, "isfriend":0, "isfamily":0}]}, "stat":"ok"}"'
The json returned by the call looks fine. Change your parsing to this:
#images = JSON.parse(#jsonresults)
That is not valid JSON. The outer set of double-quotes do not belong. This is the valid version:
'{"photos":{"page":1, "pages":500, "perpage":1, "total":500, "photo":[{"id":"8234011021", "owner":"24066605#N07", "secret":"b4c05df8c5", "server":"8341", "farm":9, "title":"Crescent Lake", "ispublic":1, "isfriend":0, "isfamily":0}]}, "stat":"ok"}'

ActiveSupport::JSON.decode does not properly handle literal line breaks

Is this the expected behavior? Note how the line break character gets lost.
ruby-1.9.2-p136 :001 > ActiveSupport::JSON.decode("{\"content\": \"active\n\nsupport\"}")
=> {"content"=>"active\nsupport"}
The same happens with unicode-escaped line breaks:
ruby-1.9.2-p136 :002 > ActiveSupport::JSON.decode("{\"content\": \"active\u000a\u000asupport\"}")
=> {"content"=>"active\nsupport"}
I'm using rails 3.0.3.
I eventually came across this ticket: https://rails.lighthouseapp.com/projects/8994/tickets/3479-activesupportjson-fails-to-decode-unicode-escaped-newline-and-literal-newlines
It seems this is a bug in ActiveSupport that will be fixed in Rails 3.0.5. For now I have patched activesupport and things are working as expected.
ruby-1.9.2-p136 :001 > ActiveSupport::JSON.decode("{\"content\": \"active\n\nsupport\"}")
=> {"content"=>"active\n\nsupport"}
To represent a newline in JSON data using double quotes, you must escape the newline:
ActiveSupport::JSON.decode("{\"content\": \"active\\n\\nsupport\"}")
Otherwise, you are inserting a newline into the JSON source and not the JSON data. Note that this would also work:
ActiveSupport::JSON.decode('{"content": "active\n\nsupport"}')
By using single quotes, you are no longer inserting a literal newline into the source of the JSON.
It is interesting to note the way ActiveSupport handles this by default (the default JSON backend is ActiveSupport::JSON::Backends::Yaml). By installing the json gem and changing the JSON backend to it (ActiveSupport::JSON.backend = 'JSONGem') and attempting to decode the same text (ActiveSupport::JSON.decode("{\"content\": \"active\\n\\nsupport\"}")) you get the following:
JSON::ParserError: 737: unexpected token at '{"content": "active
support"}'

Resources