Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to return JSON from Rails with camelcased key names

I'm building a JS app with a Rails backend and in order not to confuse snake and camel cases, I want to normalize it all by returning camelcase key names from the server. So user.last_name would return user.lastName when returned from the API.

How do I achieve this? Thanks!

Edit: Added Controller Code

class Api::V1::UsersController < API::V1::BaseController
  # authorize_resource
  respond_to :json, only: [:index]
  def sky
      @user = User.find_by_id(params[:user_id])

      if @user
          obj =  {
              sky: {
                  sectors: @user.sectors,
                  slots: @user.slots
              }
          }

          render json: obj
      else
          raise "Unable to get Sky"
      end
  end
end
like image 802
Zack Shapiro Avatar asked Jun 16 '17 20:06

Zack Shapiro


3 Answers

The way I do it is using ActiveModelSerializer and the json_api adapter:

In your Gemfile, add:

gem 'active_model_serializers'

Create a new file /config/initializers/ams.rb containing:

ActiveModelSerializers.config.adapter = :json_api
ActiveModelSerializers.config.key_transform = :camel_lower

Your controller action should look like this:

class ApiController < ApplicationController
  def sky
    @user = User.find_by_id(params[:user_id])

    if @user
      render json: @user, serializer: UserSkySerializer
    else
      raise "Unable to get Sky"
    end
  end
end

Now you need to create a serializer. First, create a new directory app/serializers/.

Next, create a new serializer app/serializers/user_sky_serializer.rb, containing:

class UserSkySerializer < ActiveModel::Serializer
  attributes :sectors, :slots
end

The result will be similar to what you describe in your obj hash, but all attribute keys will be rendered in camelCase using the jsonapi standard.

like image 153
moveson Avatar answered Sep 28 '22 01:09

moveson


Another option is the use the olive_branch gem. As described in this post, all you need to do is:

  1. Add this gem
  2. add config.middleware.use OliveBranch::Middleware in application.rb.

Then, add this header to requests from your client-side app:

'X-Key-Inflection': 'camel'

If you are using libs like axios, you can add this header to a constant along with other headers:

const HEADERS = {
  ...
  'X-Key-Inflection': 'camel'
}

const request = axios.post(url, param, HEADERS)

This way you don't need to deep_transform keys manually on the server side. Even deeply-nested json keys will be camelized. Example response from such request:

[
  {
    "id": 1,
    "firstName": "Foo",
    "lastName": "Bar",
    "createdAt": ...,
    "updatedAt": ...,
    ...
    "cabinAssignments": [
      {
        "id": 1,
        "cabinKeeperId": 1,
        "userId": 1,
        "houseId": 1,
        ...
      }
    ]
  }
]
like image 24
dimitry_n Avatar answered Sep 28 '22 01:09

dimitry_n


You don't mention your Rails version, so for others who look for this, I'll mention that in Rails 5 the answer is to use #camelize from ActiveSupport::Inflector. In my case, I had to call it in a chain on an ActiveRecord model (t below):

  def index
    trucks = AvailableTruck.all.map do |t|
      t.as_json(only: AvailableTruck.exposed)
       .deep_transform_keys(&:camelize).deep_transform_values(&:upcase)
    end
    render json: trucks
  end

#deep_transform_keys may or may not be necessary depending on your application.

like image 35
Derrell Durrett Avatar answered Sep 28 '22 01:09

Derrell Durrett