Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby (Rails) unescape a string -- undo Array.to_s

Have been hacking together a couple of libraries, and had an issue where a string was getting 'double escaped'.

for example: Fixed example

 > x = ['a']
 => ["a"] 
 > x.to_s
 => "[\"a\"]" 
 > 

Then again to

\"\[\\\"s\\\"\]\"

This was happening while dealing with http headers. I have a header which will be an array, but the http library is doing it's own character escaping on the array.to_s value.

The workaround I found, was to convert the array to a string myself, and then 'undo' the to_s. Like so: formatted_value = value.to_s

if value.instance_of?(Array)
  formatted_value = formatted_value.gsub(/\\/,"") #remove backslash                                                 
  formatted_value = formatted_value.gsub(/"/,"")  #remove single quote
  formatted_value = formatted_value.gsub(/\[/,"") #remove [                                                                                                     
  formatted_value = formatted_value.gsub(/\]/,"") #remove ]   
end
value = formatted_value

... There's gotta be a better way ... (without needing to monkey-patch the gems I'm using). (yeah, this break's if my string actually contains those strings.)

Suggestions?

** UPDATE 2 **

Okay. Still having troubles in this neighborhood, but now I think I've figured out the core issue. It's serializing my array to json after a to_s call. At least, that seems to be reproducing what I'm seeing.

['a'].to_s.to_json

I'm calling a method in a gem that is returning the results of a to_s, and then I'm calling to_json on it.

like image 562
John Hinnegan Avatar asked Feb 24 '23 21:02

John Hinnegan


1 Answers

I've edited my answer due to your edited question:

I still can't duplicate your results!

>> x = ['a']
=> ["a"]
>> x.to_s
=> "a"

But when I change the last call to this:

>> x.inspect
=> "[\"a\"]"

So I'll assume that's what you're doing?

it's not necessarily escaping the values - per se. It's storing the string like this:

%{["a"]}

or rather:

'["a"]'

In any case. This should work to un-stringify it:

>> x = ['a']
=> ["a"]
>> y = x.inspect
=> "[\"a\"]"
>> z = Array.class_eval(y)
=> ["a"]
>> x == z
=> true

I'm skeptical about the safe-ness of using class_eval though, be wary of user inputs because it may produce un-intended side effects (and by that I mean code injection attacks) unless you're very sure you know where the original data came from, or what was allowed through to it.

like image 181
nzifnab Avatar answered Mar 01 '23 09:03

nzifnab