Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hard to return preformatted json with application/json content-type #1989

Closed
iabdulin opened this issue Feb 9, 2020 · 9 comments
Closed

Comments

@iabdulin
Copy link

iabdulin commented Feb 9, 2020

For example, we have the following endpoint, returning preformatted json (I return json right from the database)

get 'all_json' do
   {key: 123}.to_json
end

Here's what will be returned:
"{\"key\":123}" with application/json content-type
Grape applies additional .to_json call.

Now let's try to fix this problem, taking into assumption that I already have a prebuilt JSON in my endpoint.

Options:

  1. Adding env['api.format'] = :binary or :txt{"key":123} but empty content-type

  2. Adding content_type 'application/json' or header 'Content-Type', 'application/json' to :txt or :binary format — "{\"key\":123}"

The only way I was able to solve this is by overwriting :json formatter with:

formatter :json, ->(object, env) {
      if object.is_a?(String)
        object
      else
        return object.to_json if object.respond_to?(:to_json)
        Grape::Json.dump(object)
      end
    }

Maybe there's another way?

@dblock
Copy link
Member

dblock commented Feb 10, 2020

I think in your case a custom formatter for JSON is the right answer.

You don't have pre-built JSON, you have a string. Grape can't guess that it's JSON. And the JSON formatter will translate a string into ... JSON.

@dblock dblock closed this as completed Feb 10, 2020
@iabdulin
Copy link
Author

iabdulin commented Feb 10, 2020

My issue is that even if I explicitly set a :txt or :binary formatter, it still applies :json formatter when I set
content_type 'application/json'
or
header 'Content-Type', 'application/json'.

Setting a content_type or header should not overwrite formatter.

This:

env['api.format'] = :binary # or :txt
content_type 'application/json' # or header 'Content-Type', 'application/json'
{key: 123}.to_json

outputs
"{\"key\":123}"

@dblock
Copy link
Member

dblock commented Feb 10, 2020

You're sending JSON, not binary. So you should just be replacing the default JSON formatter with yours with formatter :json,-> as you did above. Does that not work?

@iabdulin
Copy link
Author

It works, I just think that there should be a way to specify 'application/json' header without grape applying :json formatter.
I couldn't find a way to send this header.

env['api.format'] = :txt — sends empty content-type
adding content_type 'application/json' or header 'Content-Type', 'application/json' invokes :json formatter

@iabdulin
Copy link
Author

Even if I do this:

env['api.format'] = :txt
content_type 'application/json'
body {key: 123}.to_json

grape still applies :json formatter

@dblock
Copy link
Member

dblock commented Feb 10, 2020

This should work as is, and we have specs for this. I think something else is going on.

Turn it onto a spec or a small repro of some kind? Maybe add an example to https://github.com/ruby-grape/grape-on-rack?

@waynerobinson
Copy link

I'm having exactly the same issue.

If this is used:

env['api.format'] = :binary # or :txt
content_type 'application/json' # or header 'Content-Type', 'application/json'
{key: 123}.to_json

Then it still calls the JSON formatter. If the content_type method is left off, it doesn't.

@waynerobinson
Copy link

Here is an example using grape-on-rack:

https://github.com/waynerobinson/grape-on-rack

Please take a look at the extra methods added to Acme::Ping.

The only one that doesn't call the JSON formatter is the one where the content type is set to text/plain.

@dblock
Copy link
Member

dblock commented Mar 30, 2021

This does look like a bug, and shouldn't have been closed. Let's fix it in #2171.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants