Active_model_serializers: CamelCase JSON format

Created on 9 Oct 2013  路  21Comments  路  Source: rails-api/active_model_serializers

Is there a recommended way how to produce camelized keys by default during serialization by using AMS?

In small APIs one can just override the attributes hash, but is not a feasible way for bigger APIs.

I guess that probably the best way would be to fork AMS and camelize the keys somewhere in the overriden serialize method? Or do someone has better idea?

Btw some interesting links about snake_case vs. CamelCase in JSON:

Most helpful comment

Other option is to add:
ActiveModel::Serializer.config.key_transform = :camel_lower ActiveModel::Serializer.config.default_includes = "**"

To the: active_model_serializers.rb

Everything that goes through the serializer will be camelCase

All 21 comments

I've been wondering about the same thing, this is what I've come up with so far:

I've extended the Hash class to allow easy camelization/underscoring of keys:

class Hash
  def camelize_keys!
    update_keys!(:camelize, :lower)
  end

  def underscore_keys!
    update_keys!(:underscore)
  end

  def update_keys!(method, *args)
    self.keys.each do |key|
      updated_key = key.to_s.send(method, *args).to_sym
      self[updated_key] = self.delete(key)
      self[updated_key].update_keys!(method, *args) if self[updated_key].kind_of? Hash
    end
    self
  end
end

I've created a BaseSerializer class that all my serializers inherit from in which I override #attributes:

class BaseSerializer < ActiveModel::Serializer
  def attributes
    super.camelize_keys!
  end
end

And in my ApplicationController I'll set a before filter to update the params to underscores.

Curious to get some feedback on that

Nice one, this seems reasonable, thank you @jurre for sharing!

Just figured out that in order to also correctly camelize any has_many attributes I had to overwrite has_many as well, the same would go for has_one, both call associate so it might be interesting to look into overwriting that.

class BaseSerializer < ActiveModel::Serializer
  def attributes
    super.camelize_keys!
  end

  def self.has_many(*args)
    options = args.extract_options!
    options.reverse_merge!({ key: args.first.to_s.camelize(:lower).to_sym })
    args << options
    super(*args)
  end
end

What about doing something like ...

class ApplicationSerializer < ActiveModel::Serializer
  def serializable_hash(options={})
    Hash[super.to_a.map { |k, v| [k.to_s.camelize, v] }]
  end
end

Check it out if something like works for you and let me know.
Also test that using master please.
Thanks.

I will provide some conveniences for converting keys in 0.9

Thanks @spastorino, I'll give that a try, we would probably need to call to_s on the key first for it to work though (there's no camelize on Symbol I think)

Yep, fixed!

I created a pull request for this in #428 would love some feedback on it.

:+1:

If you prefer lowerCamelCase and symbol keys, you may want something like this (doesn't support has_many):

class ApplicationSerializer < ActiveModel::Serializer
  private

  def attributes
    super.map { |k, v| [ k.to_s.camelize(:lower).to_sym, v ] }.to_h
  end
end

This will be handled by individual adapters in 0.10, as per their formats.

Has anyone written a camelcase adapter for 0.10?

@ratbeard no, we haven't build a specific CamelCase adapter yet.

Some models have trailing questionmarks in method names like model.was_good? and I wanted it to translate to wasGood in JSON. Here's my solution. Some repetition for has_many/has_one/belongs_to - how would you simplify it?

class ApplicationSerializer < ActiveModel::Serializer
  def attributes(options={})
    super(options).map { |k, v| [ k.to_s.camelize(:lower).chomp('?').to_sym, v ] }.to_h
  end

  def self.has_many(*args)
    options = args.extract_options!
    options.reverse_merge!({ key: args.first.to_s.camelize(:lower).to_sym })
    args << options
    super(*args)
  end
  def self.has_one(*args)
    options = args.extract_options!
    options.reverse_merge!({ key: args.first.to_s.camelize(:lower).to_sym })
    args << options
    super(*args)
  end
  def self.belongs_to(*args)
    options = args.extract_options!
    options.reverse_merge!({ key: args.first.to_s.camelize(:lower).to_sym })
    args << options
    super(*args)
  end
end

Here's the current code for associations in AMS: https://github.com/rails-api/active_model_serializers/blob/aaa60bfdc131cbd96b322037f56bce99a9f36de5/lib/active_model/serializer/associations.rb

hey ya'll

Just wanted to point out: https://github.com/domchristie/humps as a nice way to not have to change the API format (I'm partial to snake_case for API data) to fit the frontend library (React in my case).

Also: https://github.com/substack/camelize

It looks like using a key_transform might be a good solution for this

there is now also https://github.com/NullVoxPopuli/case_transform
which will eventually be pulled in to AMS when I get it having native extensions

@NullVoxPopuli, looking forward to it.

@thePooh case_transform is in AMS now, so you can optionally use the native extensions variant

Other option is to add:
ActiveModel::Serializer.config.key_transform = :camel_lower ActiveModel::Serializer.config.default_includes = "**"

To the: active_model_serializers.rb

Everything that goes through the serializer will be camelCase

Other option is to add:
ActiveModel::Serializer.config.key_transform = :camel_lower ActiveModel::Serializer.config.default_includes = "**"

To the: active_model_serializers.rb

Everything that goes through the serializer will be camelCase

This works fine for me. I could use it for different scopes in my app:

class BaseSerializer < ActiveModel::Serializer
    ActiveModel::Serializer.config.key_transform = :underscore

 end
Was this page helpful?
0 / 5 - 0 ratings

Related issues

iggant picture iggant  路  4Comments

NullVoxPopuli picture NullVoxPopuli  路  4Comments

Tybot204 picture Tybot204  路  3Comments

Andriykoo picture Andriykoo  路  5Comments

seoyoochan picture seoyoochan  路  4Comments