Ruby on Rails Advanced JSON Serialization

Can I reduce duplication in the serialization of a ruby hash?

HTTParty, by default, converts the :query hash into what it calls 'rails style query parameters':

For a query:

get '/', query: {selected_ids: [1,2,3]}

The default query string looks like this:

/?selected_ids[]=1&selected_ids[]=2&selected_ids[]=3

Since you are doing a POST, it is possible/preferable to send your hash in the body of the request rather than in the query string.

def post_com(hsh)
self.class.post('some_url', body: hsh.to_json, headers: headers, format: :plain)
end

This has the advantage that it doesn't do any transformation of the payload and the query string length limit doesn't apply anyway.

For the record, you can disable the default 'rails style' encoding like this:

class Api
include HTTParty
disable_rails_query_string_format

...
end

You can also roll your own custom query string normalizer by passing a Proc to query_string_normalizer.

Rails return JSON serialized attribute with_indifferent_access

use the built-in serialize method :

class Whatever < ActiveRecord::Base
serialize :params, HashWithIndifferentAccess
end

see ActiveRecord::Base docs on serialization for more info.

Rails as_json with conditions

I think you could try add some method like active_bars which will return exactly what you need like:

def active_bars
bars.where active: true
end

or you could even add new relation:

has_many :active_bars, -> { where active: true }, class_name: '..', foreign_id: '..'

and then you will be able write:

@foo.as_json(
except: [:created_at, :updated_at],
include: {
active_bars: { only: [:ip_addr, :active] }
}
)

How to serialize/deserialize ruby hashes/structs with objects as keys to json

JSON only allows strings as object keys. For this reason to_s is called for all keys.

You'll have the following options to solve your issue:

  1. The best option is changing the data structure so it can properly be serialized to JSON.

  2. You'll have to handle the stringified key yourself. An Hash produces a perfectly valid Ruby syntax when converted to a string that can be converted using Kernel#eval like Andrey Deineko suggested in the comments.

    result = json.transform_keys { |key| eval(key) }
    # json.transform_keys(&method(:eval)) is the same as the above.

    The Hash#transform_keys method is relatively new (available since Ruby 2.5.0) and might currently not be in you development environment. You can replace this with a simple Enumerable#map if needed.

    result = json.map { |k, v| [eval(k), v] }.to_h

    Note: If the incoming JSON contains any user generated content I highly sugest you stay away from using eval since you might allow the user to execute code on your server.



Related Topics



Leave a reply



Submit