I have a string with \n as a join result:
my_var = ['name','phone','age'].join("\n")
I will send this string in the body of a post as a Json:
def body
{ "str": my_var }
end
I want to send the var in multiple lines instead of sending the \n like this:
"name\nphone\nage"
EDIT:
I am sending this string joined with \n to another dev team as a json in the body of my post request to their uri. But they don't want to receive a string with \n and replace or translate there. They want to recieve in multiple lines.
You can use different separator and then, on receive, separate lines from whole string based on that delimiter using
my_delimiter = '\n' or my_delimiter = ';'
lines = my_var.split(my_delimiter).
Or you could iterate over ['name','phone','age'] and add them as separate json elements.
If this doesn't help, then please clarify your question.
They are receiving multiple lines, depending on their OS: https://en.wikipedia.org/wiki/Newline
2.1.10 :001 > my_var = ['name','phone','age'].join("\n")
=> "name\nphone\nage"
2.1.10 :002 > puts my_var
name
phone
age
=> nil
2.1.10 :003 > my_var.to_json
=> "\"name\\nphone\\nage\""
2.1.10 :004 > puts my_var.to_json
"name\nphone\nage"
=> nil
2.1.10 :005 >
The text you're sending them contains instructions on where a line break is (i.e. the \n character). The graphical display of it is up to their end.
That's the expected format of the JSON. You should not be including a new line in the values, but using the '\n' character.
json = { text: ['name','phone','age'].join("\n") }.to_json
puts JSON.parse( json )['text']
you can see the parse is parsing it correctly.
pry(main)> puts JSON.parse( json )['text']
name
phone
age
=> nil
Related
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.
I'm having problem with special characters when casting a hash to a json string.
Everything works fine with Ruby 2.0 / Rails 3.2.21, that is,
puts "“".to_json
#"\u201c"
But with Ruby 2.3.0 / Rails 4.2.5.1 I get
puts "“".to_json
#"“"
Is there any way to force Ruby 2.3.0 to convert special characters to unicode style strings (\uXXXX) ?
Remark:
Notice that in Ruby 2.3 / Rails 4, we get
"“".to_json.bytesize == 5 #true
However, in 2.0 we get
"“".to_json.bytesize == 8 #true
So clearly it's the string itself that is different, not different output formats.
I ❤ Rails (just kidding.)
In Rails3 there was a hilarious method to damage UTF-8 in JSON. Rails4, thanks DHH, freed from this drawback.
So, whether one wants the time-back machine, the simplest way is to monkeypatch ::ActiveSupport::JSON::Encoding#escape:
module ::ActiveSupport::JSON::Encoding
def self.escape(string)
if string.respond_to?(:force_encoding)
string = string.encode(::Encoding::UTF_8, :undef => :replace)
.force_encoding(::Encoding::BINARY)
end
json = string.
gsub(escape_regex) { |s| ESCAPED_CHARS[s] }.
gsub(/([\xC0-\xDF][\x80-\xBF]|
[\xE0-\xEF][\x80-\xBF]{2}|
[\xF0-\xF7][\x80-\xBF]{3})+/nx) { |s|
s.unpack("U*").pack("n*").unpack("H*")[0].gsub(/.{4}/n, '\\\\u\&')
}
json = %("#{json}")
json.force_encoding(::Encoding::UTF_8) if json.respond_to?(:force_encoding)
json
end
end
More robust solution would be to corrupt the result:
class String
def rails3_style
string = encode(::Encoding::UTF_8, :undef => :replace).
force_encoding(::Encoding::BINARY)
json = string.
gsub(/([\xC0-\xDF][\x80-\xBF]|
[\xE0-\xEF][\x80-\xBF]{2}|
[\xF0-\xF7][\x80-\xBF]{3})+/nx) { |s|
s.unpack("U*").pack("n*").unpack("H*")[0].gsub(/.{4}/n, '\\\\u\&')
}
json = %("#{json}")
json.force_encoding(::Encoding::UTF_8) if json.respond_to?(:force_encoding)
json
end
end
puts "“".to_json.rails3_style
#⇒ "\u201c"
I hardly could understand why anybody might want to do this on purpose, but the solution is here.
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
In my Rails application I have a field address which is a varchar(255) in my SQLite database.
Yet whenever I save an address consisting of more than one line through a textarea form field, one mysterious whitespace character gets added to the right.
This becomes visible only when the address is right aligned (like e.g. on a letterhead).
Can anybody tell me why this is happening and how it can be prevented?
I am not doing anything special with those addresses in my model.
I already added this attribute writer to my model but it won't remove the whitespace unfortunately:
def address=(a)
write_attribute(:address, a.strip)
end
This is a screenshot:
As you can see only the last line is right aligned. All others contain one character of whitespace at the end.
Edit:
This would be the HTML output from my (Safari) console:
<p>
"John Doe "<br>
"123 Main Street "<br>
"Eggham "<br>
"United Kingdom"<br>
</p>
I don't even know why it's putting the quotes around each line... Maybe that's part of the solution?
I believe textarea is returning CR/LF for line separators and you're seeing one of these characters displayed between each line. See PHP displays \r\n characters when echoed in Textarea for some discussion of this. There are probably better questions out there as well.
You can strip out the whitespace at the start and end of each line. Here are two simple techniques to do that:
# Using simple ruby
def address=(a)
a = a.lines.map(&:strip).join("\n")
write_attribute(:address, a)
end
# Using a regular expression
def address=(a)
a = a.gsub(/^[ \t]+|[ \t]+$/, "")
write_attribute(:address, a)
end
I solved a very similar kind of problem when I ran into something like this,
(I used squish)
think#think:~/CrawlFish$ irb
1.9.3-p385 :001 > "Im calling squish on a string, in irb".squish
NoMethodError: undefined method `squish' for "Im calling squish on a string, in irb":String
from (irb):1
from /home/think/.rvm/rubies/ruby-1.9.3-p385/bin/irb:16:in `<main>'
That proves, there is no squish in irb(ruby)
But rails has squish and squish!(you should know the difference that bang(!) makes)
think#think:~/CrawlFish$ rails console
Loading development environment (Rails 3.2.12)
1.9.3-p385 :001 > str = "Here i am\n \t \n \n, its a new world \t \t \n, its a \n \t new plan\n \r \r,do you like \r \t it?\r"
=> "Here i am\n \t \n \n, its a new world \t \t \n, its a \n \t new plan\n \r \r,do you like \r \t it?\r"
1.9.3-p385 :002 > out = str.squish
=> "Here i am , its a new world , its a new plan ,do you like it?"
1.9.3-p385 :003 > puts out
Here i am , its a new world , its a new plan ,do you like it?
=> nil
1.9.3-p385 :004 >
Take a loot at strip! method
>> #title = "abc"
=> "abc"
>> #title.strip!
=> nil
>> #title
=> "abc"
>> #title = " abc "
=> " abc "
>> #title.strip!
=> "abc"
>> #title
=> "abc"
source
What's the screen shot look like when you do:
def address=(a)
write_attribute(:address, a.strip.unpack("C*").join('-') )
end
Update based on comment answers. Another way to get rid of the \r's at the end of each line:
def address=(a)
a = a.strip.split(/\r\n/).join("\n")
write_attribute(:address, a)
end
When I try to return JSON in the format shown above, my JSON looks like this
result = JSON.parse(data)
p result.to_json
#json from .to_json
\"is_claimed\": true,
\"rating\": 3.5,
\"mobile_url\": \"http: //m.yelp.com/biz/rudys-barbershop-seattle\",
...
When I use "p result" instead (without .to_json), I get the below:
"is_claimed"=>true,
"rating"=>3.5,
"mobile_url"=>"http://m.yelp.com/biz/rudys-barbershop-seattle",
....
The first has a '\' character and the second uses a hash rocket. How do I return JSON in a normal format?
The format you're seeing is because of the way p outputs information, try changing your output to puts.
data = '{
"is_claimed":true,
"rating":3.5,
"mobile_url":"http://m.yelp.com/biz/rudys-barbershop-seattle"
}'
result = JSON.parse(data)
puts result.to_json
EDIT: Some additional information on p vs puts: p vs puts in Ruby
That's because you are using p to display the contents of a string.
p "hi\"there"
"hi\"there"
=> "hi\"there"
[2] pry(main)> puts "hi\"there"
hi"there
Also, you should probably be aware of the difference between the methods as_json and to_json, see http://jonathanjulian.com/2010/04/rails-to_json-or-as_json/ to understand the difference.
Not sure what you mean by "normal format", I sometimes puts it out by
puts JSON.generate(result)
to get it in a friendly format.