Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Force JSON serialization of numbers to specific precision

Tags:

json

ruby

Consider the following code that is intended to round numbers to the nearest one-hundredth and serialize the result to JSON:

require 'json'
def round_to_nearest( value, precision )
  (value/precision).round * precision
end
a = [1.391332, 0.689993, 4.84678]
puts a.map{ |n| round_to_nearest(n,0.01) }.to_json
#=> [1.3900000000000001,0.6900000000000001,4.8500000000000005]

Is there a way to use JSON to serialize all numbers with a specific level of precision?

a.map{ ... }.to_json( numeric_decimals:2 )
#=> [1.39,0.69,4.85]

This could be either with the Ruby built-in JSON library or another JSON gem.

Edit: As noted in comments to answers below, I'm looking for a general solution to all JSON serialization for arbitrary data that includes numbers, not specifically a flat array of numbers.


Note that the above problem can be fixed in this specific case by rewriting the method:

def round_to_nearest( value, precision )
  factor = 1/precision
  (value*factor).round.to_f / factor
end

...but this does not solve the general desire to force a precision level during serialization.

like image 204
Phrogz Avatar asked Oct 07 '22 01:10

Phrogz


1 Answers

I'd just pre-round it using ruby's built-in round method: http://www.ruby-doc.org/core-1.9.3/Float.html#method-i-round

a.map{ |n| n.round(2) }.to_json

That looks clean to me instead of getting all types of custom libraries and passing in arguments.

Edit for comment:

I know you can do that with activesupport.

# If not using rails
require 'active_support/json'

class Float
  def as_json(options={})
    self.round(2)
  end
end

{ 'key' => [ [ 3.2342 ], ['hello', 34.1232983] ] }.to_json
# => {"key":[[3.23],["hello",34.12]]}

More exact solution: better monkey-patch

like image 140
AJcodez Avatar answered Oct 13 '22 09:10

AJcodez