Cautious when convert a BigDecimal value to JSON in Rails

Blog-2-Ruby-on-Rails-2-1110x0-c-default

In Ruby on Rails, we can use to_json to convert data or hash to JSON easily, but we need to be cautious when we convert numeric data to JSON in Rails. In this article we are going to share about how Rails treats BigDecimal differently besides other numeric data type.

Rails serializes BigDecimal as string when we convert to JSON

# store float number to variable float_number
pry(main)> float_number = Float 123
=> 123.0

# store big decimal number to variable big_decimal_number
pry(main)> big_decimal_number = BigDecimal 123
=> 0.123e3

# convert the data to JSON
pry(main)> json_data = { float_number: float_number, big_decimal_number: big_decimal_number }.to_json
=> "{\"float_number\":123.0,\"big_decimal_number\":\"123.0\"}"

# parse JSON to variable parsed_json_data to check the data
pry(main)> parsed_json_data = JSON.parse json_data
=> {"float_number"=>123.0, "big_decimal_number"=>"123.0"}

# check the class of "float_number"
pry(main)> parsed_json_data["float_number"].class
=> Float

## check the class of "big_decimal_number"
pry(main)> parsed_json_data["big_decimal_number"].class
=> String

We can look at the example above in Rails Console, we created 2 data with different numeric type and converted to JSON and using .class to check the the data type. Rails keeps float_number as Float but serializes BigDecimal as String .

How we can fix this?

There are 3 ways to fix this issue when you need BigDecimal in your JSON

  1. In Rails version before 4.1 we can add ActiveSupport::JSON::Encoding.encode_big_decimal_as_string = false to your rails application config (config/application.rb) to disable rails serializes BigDecimal as String in JSON, but it has been deprecated in Rails 4.1.
  2. For the Rails version above 4.1, We can use gem activesupport-json_encoder to achieve the same goal. This gem was extracted from the Rails framework (This gem not supported in Rails 5)
  3. You can monkey patching as_json in BigDecimal
class BigDecimal
  def as_json
    to_d
  end
end


Conclusion

From this document we know that client may get the wrong number because most libraries parse non-integer JSON numbers directly as floats. Therefore the safest way is convert the data to String to keep the real value. However, you still can use the solutions above to convert your BigDecimal data to numeric in JSON.

Share on twitter
Twitter
Share on telegram
Telegram
Share on facebook
Facebook
Share on linkedin
LinkedIn
Share on email
Email

Leave a Comment

Your email address will not be published. Required fields are marked *