Skip to content

Why do I have to call .as_json twice to get a proper representation #313

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

Open
bobbytables opened this issue Jan 25, 2019 · 2 comments
Open

Comments

@bobbytables
Copy link

Hi! I'm trying to use my entity to ensure the returned data in the API matches what my Entity should be exposing in a RSpec request spec in my rails application.

I'm doing this:

it 'returns the change events for the incident as json' do
  authed_get "/v1/incidents/#{incident.id}/related_change_events"

  expect(parsed['data']).to match_array(PublicAPI::V1::Incidents::RelatedChangeEventEntity.represent(related_change_events).as_json.as_json)
end

This makes my test pass, but why do I have to call #as_json twice? This feels weird to me and I don't see a method on the Grape::Entity class that gives me what I want. More of a question than a bug but I see room for improvement here.

Thanks!

@synth
Copy link

synth commented Apr 19, 2021

We're hitting this too, in a way. Calling .as_json doesn't seem to return a hash for nested entities. Oddly, calling .to_json will return a string that has been properly recursed and converted to json.

In other words, calling .as_json converts the top level entity to a hash, but nested entities remain as type: Grape::Entity::Exposure::NestingExposure::OutputBuilder. This means you can't do things like deep_stringify_keys or otherwise work with this structure.

I'm not sure, but I would guess you need to call .as_json for every level of nesting, its not just that its magically needing to call it twice.

Tested this with latest 0.9.0 version

@jweir
Copy link

jweir commented May 9, 2025

This recently caused a surprise in our results. The Grape as_json is not the same as Rails as_json. We have a CSV and JSON response, the times were getting formatted differently and took a while to understand why.

class Ex < Grape::Entity
  root :examples
  expose :t
end

time = Time.now
sample = [{t: time}]

a = Ex.represent(sample)
puts a.as_json
# {"examples"=>[{:t=>2025-05-09 01:24:05.476475079 +0000}]}

puts a.as_json.as_json
# {"examples"=>[{"t"=>"2025-05-09T01:24:05.476+00:00"}]}

In the second call the time object gets converted to JSON.

One possible solution is to deprecate as_json in favor of the serializable_hash method. This might be less surprising as the developer wouldn't expect any "jsonification" to have occurred.

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

No branches or pull requests

3 participants