I have done this a thousand times but I'm still not comfortable with how the render :json
handles strings.
To set a scope let's talk about Rails 3
This is how it behaves right now:
... render :json => 'This is the string' ...
Will be returning to the browser:
This is the string
That's actually not a valid JSON response :S
Ideally it should be rendering something like this:
"This is the string"
Even the rails guides say:
You don’t need to call to_json on the object that you want to render. If you use the :json option, render will automatically call to_json for you.
And calling "This is the string".to_json
is actually returning "\"This is the string\""
as expected.
"This is the string".to_json #=> "\"This is the string\""
Am I so wrong ?
To check if a string is JSON in JavaScript, we can use the JSON. parse method within a try-catch block. to check if jsonStr is a valid JSON string. Since we created the JSON string by calling JSON.
Simple function to validate JSON. If you have to validate your JSON in multiple places, you can always use the following function. function is_valid_json( $raw_json ){ return ( json_decode( $raw_json , true ) == NULL ) ? false : true ; // Yes!
A JSON string contains either an array of values, or an object (an associative array of name/value pairs). An array is surrounded by square brackets, [ and ] , and contains a comma-separated list of values. An object is surrounded by curly brackets, { and } , and contains a comma-separated list of name/value pairs.
I agree that this is unexpected behavior at first, but it actually makes some good sense.
Consider, for example, what you would expect this to do:
output = {'foo' => 'bar'}.to_json render :json => output
Even though the to_json
is kinda redundant, you expect the result to be {foo: "bar"}
. However, note that the result of {'foo' => 'bar'}.to_json
is actually a string. So, the above code block is equivalent to:
render :json => '{foo: "bar"}'
If render
were to JSON-encode strings passed to :json
, you would get "{foo: \"bar\"}"
, which is definitely not expected behavior.
So here's the deal: render
checks to see if the :json
argument is a string. If so, it assumes that it's a JSON string and you already ran to_json
, and passes the string along. If not, it runs to_json
on the object.
I think the documentation should probably clarify that, but there you have it. Though it's not exactly intuitive at first glance, I would be surprised if it worked any other way.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With