如何使用camelcased键名从Rails返回JSON

时间:2017-06-16 20:14:55

标签: ruby-on-rails ruby rails-api camelcasing

我正在构建一个带有Rails后端的JS应用程序,为了不混淆蛇和骆驼的情况,我想通过从服务器返回camelcase密钥名称来规范化它。因此,user.last_name从API返回时会返回user.lastName

我如何实现这一目标?谢谢!

修改:添加了控制器代码

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

4 个答案:

答案 0 :(得分:11)

我这样做的方法是使用ActiveModelSerializer和json_api适配器:

在你的Gemfile中,添加:

gem 'active_model_serializers'

创建一个新文件/config/initializers/ams.rb,其中包含:

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

您的控制器操作应如下所示:

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

现在您需要创建一个序列化程序。首先,创建一个新目录app/serializers/

接下来,创建一个新的序列化程序app/serializers/user_sky_serializer.rb,其中包含:

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

结果类似于您在obj哈希中描述的内容,但所有属性键都将使用jsonapi标准在camelCase中呈现。

答案 1 :(得分:1)

另一个选择是使用olive_branch宝石。如this post中所述,您需要做的是:

  1. 添加此宝石
  2. config.middleware.use OliveBranch::Middleware中添加application.rb

然后,将此标头添加到客户端应用程序的请求中:

'X-Key-Inflection': 'camel'

如果您使用的是axios之类的库,则可以将此标头与其他标头一起添加到常量中:

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

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

这样,您无需在服务器端手动deep_transform键。甚至深度嵌套的json键也会被驼峰化。此类请求的示例响应:

[
  {
    "id": 1,
    "firstName": "Foo",
    "lastName": "Bar",
    "createdAt": ...,
    "updatedAt": ...,
    ...
    "cabinAssignments": [
      {
        "id": 1,
        "cabinKeeperId": 1,
        "userId": 1,
        "houseId": 1,
        ...
      }
    ]
  }
]

答案 2 :(得分:0)

你没有提到你的Rails版本,所以对于那些寻找这个的人,我会在Rails 5中提到答案是使用来自ActiveSupport::Inflector的{​​{1}}。在我的情况下,我不得不在ActiveRecord模型(t下面)的链中调用它:

  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可能需要也可能不需要。

答案 3 :(得分:-1)

您可以使用ruby的method_missing方法实现这一目标。

创建类似concerns/method_missing_extension.rb的文件,并在其中加入以下代码。

module MethodMissingExtension
  def method_missing(method_name, args = {})
    if self.class.column_names.include? method_name.to_s.underscore
      send method_name.to_s.underscore.to_sym
    else
      super
    end
  end
end

在每个模型中加入此模块,例如include MethodMissingExtension

现在只要你user.firstNameuser.first_name就会返回。