简体   繁体   中英

Dynamic root Key in ActiveModel Serializers

I am using Rails 5 and Acive Model Serializer (0.10.6) in my project. I need below format of JSON

{
   "account_lists": {
    "0": {
            "id": 1,
            "description": "test tets test tets"
          },
     "1": {
            "id": 2,
            "description": "test tets test tets"
          }
      }
}

0 , 1 keys would be the index of the object.

I tried with below code, But result is not coming

account_serializer.rb

class AccountSerializer < ActiveModel::Serializer
  attributes :custom_method

  def custom_method
    { object.id => {id: object.id, description: object. description } }
  end
end

accounts_controller.rb

render json: @accounts, root: "account_lists", adapter: :json

Result is

{
"account_lists": [
    {
        "custom_method": {
            "46294": {
                "id": 46294,
                "description": "test tets test tets"
            }
        }
    },
    {
        "custom_method": {
            "46295": {
                "id": 46295,
                "description": "test tets test tets"
            }
        }
   ]
 }

Could you please help me to get the result.

You can achieve this in two ways, using serializers or without using serializers.

To make this work with serialzers we need to write some meta programing. something like this

class AccountSerializer < ActiveModel::Serializer
    attributes

    def initialize(object, options = {})
        super
        self.class.send(:define_method, "#{object.id}") do
            {
                "#{object.id}": {
                    id: object.id,
                    description: object.description
                }
            }
        end
    end

    def attributes(*args)
        hash = super
        hash = hash.merge(self.send("#{object.id}"))
    end
end

this will produce results like this

{
    "account_lists": [
        {
          "19":{
              "id":19,
              "description":"somethign here "
            }
        },
        {
            "20":{
                "id":20,
                "description":"somethign here "
            }
        },{
            "48":{
                "id":48,
                "description":"somethign here"
            }
        }
    ]
}

if you want json response to exactly what you have mentioned in question, you better to go with a custom library class that build json for you

class BuildCustomAccountsJson

  def initialize(accounts)
    @accounts = accounts
  end

  def build_accounts_json(accounts)
    _required_json = {}

    @accounts.map do |account|
     _required_json["#{account.id}"] = { id: "#{account.id}", description: "#{account.description}" }
    end

    _required_json
  end

end

and in controller action, we can use this class

def index
  ...
  ...

  @accounts_json = BuildCustomAccountsJson.new(@accounts).build_accounts_json

  render json: @accounts_json, root: "accounts_list"
end 

this will produce json like this

{
   "account_lists": {
    "0": {
            "id": 1,
            "description": "test tets test tets"
          },
     "1": {
            "id": 2,
            "description": "test tets test tets"
          }
      }
}

That's all.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM