at.
at.

Reputation: 52510

How to modify JSON returned from Rails controller

The standard mechanism I return JSON in a Rails controller is with:

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

Is there a way to modify the @cars JSON? In particular I simply want to add 4 extra fields in there.

UPDATE: Sorry, I should've explained a little more. @cars contains a list of Car objects. I want to add 4 fields to each Car object in the JSON. This is unique to a particular controller, so I don't want to make an as_json method as that would affect other JSONs of this class.

Upvotes: 3

Views: 5297

Answers (5)

nakwa
nakwa

Reputation: 1213

You can also add custom or nested fields with something like:

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

Upvotes: 3

Muntasim
Muntasim

Reputation: 6786

If you want to edit the json then you can use ActiveSupport::JSON.decode to decode the json. It will give you an array of hash which is easily modifiable and then you can convert that to json using to_sosn

Example: I have used rails console to demonstrate. You need the last portion only.

>> 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"}]

Then you can iterate that array and modify where necessary and convert back to json

Upvotes: 0

Francesco Belladonna
Francesco Belladonna

Reputation: 11689

If you have to do it once, you should use to_json ( http://apidock.com/rails/ActiveRecord/Serialization/to_json ) in this way, directly in your controller:

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

In :methods you can specify additional methods you want include.

activemodel_serializer should be used only if you do it very often (for example on a JSON API), if you do it only once in your project, you shouldn't do it.

You can also use the default Rails 4 builder if you are actually using Rails 4.
Notice that the most famous gem for building JSON is RABL, but I do prefer activemodel_serializer. There is also a very nice railscasts available for free about it.

Upvotes: 2

lalameat
lalameat

Reputation: 754

I think it could use a method to do the adding fields process and render the return result. Could the following work for you:

In a helper

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

In your controller:

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

Upvotes: 0

deadwards
deadwards

Reputation: 1551

There are two ways that you can modify the structure of the json returned.

  1. Override the #as_json method on the model

    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. You can use the active_model_serializer gem. This is my preferred method because it comes with a few built-in conveniences.

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

Upvotes: 2

Related Questions