如何修改从Rails控制器返回的JSON

时间:2014-02-12 00:41:01

标签: ruby-on-rails json

我在Rails控制器中返回JSON的标准机制是:

respond_to do |format|
  format.html
  format.json { render json: @cars }
end

有没有办法修改@cars JSON?特别是我只想在那里添加4个额外的字段。

更新 :对不起,我应该多解释一下。 @cars包含Car个对象的列表。我想在JSON中为每个Car对象添加4个字段。这是特定控制器的 唯一 ,因此我不想制作as_json方法,因为这会影响此类的其他JSON。< / p>

5 个答案:

答案 0 :(得分:1)

有两种方法可以修改返回的json的结构。

  1. 覆盖模型上的#as_json方法

    model Car < ActiveRecord::Base
    
      def as_json(options={})
        opts = {
          :only => [:id, :name],
          :methods => [:custom_method]
        }
    
        super(options.merge(opts))
      end
    
      def custom_method
        # some extra info (possibly calculated values)
      end
    
    end
    
  2. 您可以使用active_model_serializer gem。这是我首选的方法,因为它带有一些内置的便利性。

    class CarSerializer < ActiveModel::Serializer
      attributes :id, :name, :custom_method
    
      def custom_method
        # method only available within serializer
      end
    end
    

答案 1 :(得分:1)

如果要编辑json,则可以使用ActiveSupport::JSON.decode解码json。它将为您提供一个易于修改的哈希数组,然后您可以使用to_sosn将其转换为json

示例:我使用rails控制台进行演示。你只需要最后一部分。

>> cars = [{id: 1,name: 'foo'}, {id:2, name: 'bar'}]
[{:id=>1, :name=>"foo"}, {:id=>2, :name=>"bar"}]

>> json = cars.to_json
"[{\"id\":1,\"name\":\"foo\"},{\"id\":2,\"name\":\"bar\"}]"

>> parsed_json = ActiveSupport::JSON.decode json
[{"id"=>1, "name"=>"foo"}, {"id"=>2, "name"=>"bar"}]

然后你可以迭代那个数组并在必要时修改并转换回json

答案 2 :(得分:1)

如果您必须执行一次,则应以这种方式直接在控制器中使用to_jsonhttp://apidock.com/rails/ActiveRecord/Serialization/to_json):

@object.to_json(:except => ['created_at', 'updated_at'], :methods => ['method1', 'method2'])

:methods中,您可以指定其他要包含的方法。

activemodel_serializer只有在经常这样做时才会被使用(例如在JSON API上),如果你只在项目中执行一次,你就不应该这样做。

如果您实际使用 Rails 4 ,也可以使用默认的Rails 4构建器。
请注意,用于构建JSON的最着名的gem是RABL,但我更喜欢activemodel_serializer。关于它还有一个非常好的railscasts available for free

答案 3 :(得分:1)

您还可以添加自定义或嵌套字段,例如:

class MyModel < ActiveRecord::Base

  def as_json(options)
    super(options).merge({
      "custom" => "myvalue",
      :name => self.name.titleize,
      "result" => self.my_method(self.value1)
    })
  end
end

答案 4 :(得分:0)

我认为它可以使用一种方法来添加字段进程并呈现返回结果。以下是否可以为您服务:

帮助

def some_method(in_param, from_which_controller)
  return_array = Array.new
  obj_array = JSON.parse(in_param);
  obj_array.each do |obj|
    case from_which_controller
      when from_controller_a
         # add the field to obj or some other thing
      when ...........
         # add the field to obj or some other thing
    end
    return_array << obj # or new obj instead of obj
  end
  return return_array.to_json
end

在您的控制器中:

respond_to do |format|
  format.html
  format.json { render json: some_method(@cars, this_controller) }
end