diff --git a/lib/active_model_serializers/adapter/json_api/deserialization.rb b/lib/active_model_serializers/adapter/json_api/deserialization.rb index f5244355..ff1d3785 100644 --- a/lib/active_model_serializers/adapter/json_api/deserialization.rb +++ b/lib/active_model_serializers/adapter/json_api/deserialization.rb @@ -155,7 +155,7 @@ module ActiveModelSerializers # @api private def parse_attributes(attributes, options) - attributes + transform_keys(attributes, options) .map { |(k, v)| { field_key(k, options) => v } } .reduce({}, :merge) end @@ -182,23 +182,29 @@ module ActiveModelSerializers prefix_key = field_key(assoc_name, options).to_s.singularize hash = if assoc_data.is_a?(Array) - { "#{prefix_key}_ids".to_sym => assoc_data.map { |ri| ri['id'] } } + { "#{prefix_key}_ids".to_sym => assoc_data.map { |ri| ri[:id] } } else - { "#{prefix_key}_id".to_sym => assoc_data ? assoc_data['id'] : nil } + { "#{prefix_key}_id".to_sym => assoc_data && assoc_data.is_a?(Hash) ? assoc_data[:id] : nil } end polymorphic = (options[:polymorphic] || []).include?(assoc_name.to_sym) - hash["#{prefix_key}_type".to_sym] = assoc_data['type'] if polymorphic + hash["#{prefix_key}_type".to_sym] = assoc_data[:type] if polymorphic hash end # @api private def parse_relationships(relationships, options) - relationships - .map { |(k, v)| parse_relationship(k, v['data'], options) } + transform_keys(relationships, options) + .map { |(k, v)| parse_relationship(k, v[:data], options) } .reduce({}, :merge) end + + # @api private + def transform_keys(hash, options) + transform = options[:key_transform] || :underscore + KeyTransform.send(transform, hash) + end end end end diff --git a/lib/active_model_serializers/key_transform.rb b/lib/active_model_serializers/key_transform.rb index 03cf9cef..cf120547 100644 --- a/lib/active_model_serializers/key_transform.rb +++ b/lib/active_model_serializers/key_transform.rb @@ -32,6 +32,16 @@ module ActiveModelSerializers hash.deep_transform_keys! { |key| key.to_s.dasherize.to_sym } end + # Transforms keys to underscore. + # This is the default case for deserialization in the JsonApi adapter. + # + # @example: + # "some-key" => "some_key", + # @see {https://github.com/rails/rails/blob/master/activesupport/lib/active_support/inflector/methods.rb#L89-L98 ActiveSupport::Inflector.underscore} + def underscore(hash) + hash.deep_transform_keys! { |key| key.to_s.underscore.to_sym } + end + # Returns the hash unaltered def unaltered(hash) hash diff --git a/test/action_controller/json_api/deserialization_test.rb b/test/action_controller/json_api/deserialization_test.rb index 8a57d594..0528dc55 100644 --- a/test/action_controller/json_api/deserialization_test.rb +++ b/test/action_controller/json_api/deserialization_test.rb @@ -20,7 +20,10 @@ module ActionController 'id' => 'zorglub', 'attributes' => { 'title' => 'Ember Hamster', - 'src' => 'http://example.com/images/productivity.png' + 'src' => 'http://example.com/images/productivity.png', + 'image-width' => '200', + 'imageHeight' => '200', + 'ImageSize' => '1024' }, 'relationships' => { 'author' => { @@ -34,6 +37,12 @@ module ActionController { 'type' => 'comments', 'id' => '1' }, { 'type' => 'comments', 'id' => '2' } ] + }, + 'related-images' => { + 'data' => [ + { 'type' => 'image', 'id' => '7' }, + { 'type' => 'image', 'id' => '8' } + ] } } } @@ -46,9 +55,13 @@ module ActionController 'id' => 'zorglub', 'title' => 'Ember Hamster', 'src' => 'http://example.com/images/productivity.png', + 'image_width' => '200', + 'image_height' => '200', + 'image_size' => '1024', 'author_id' => nil, 'photographer_id' => '9', - 'comment_ids' => %w(1 2) + 'comment_ids' => %w(1 2), + 'related_image_ids' => %w(7 8) } assert_equal(expected, response)