Ruby json库将BigDecimal转换为科学记数法

时间:2017-07-31 16:40:32

标签: json ruby

我需要将包含一些BigDecimal字段的Ruby哈希转换为JSON。

我需要将BigDecimal转换为Float / Integer,但是' json' lib总是将其转换为科学记数法。

require 'json'
require 'bigdecimal'

obj = {}
obj['created_at'] = BigDecimal('0.12345')

puts "JSON.dump(obj) = #{JSON.dump(obj)}"
puts "JSON.generate(obj) = #{JSON.generate(obj)}"
puts "JSON.fast_generate(obj) = #{JSON.fast_generate(obj)}"
puts "JSON.pretty_generate(obj) = #{JSON.pretty_generate(obj)}"

结果:

JSON.dump(obj) = {"created_at":"0.12345e0"}
JSON.generate(obj) = {"created_at":"0.12345e0"}
JSON.fast_generate(obj) = {"created_at":"0.12345e0"}
JSON.pretty_generate(obj) = {
  "created_at": "0.12345e0"
}

是否有任何JSON库可以指定数字格式,因此当我解析一个对象时,BigDecimal字段不会被转换为科学记数法?

obj['created_at'] = BigDecimal.new('0.12345')
JSON.parse(obj) = { "created_at": "0.12345" } # not 0.12345e0

我使用ruby 2.4.1p111

2 个答案:

答案 0 :(得分:0)

$3

应该给你想要的结果。

<强>更新

BigDecimal('0.12345').to_f

答案 1 :(得分:0)

JSON库要求对象具有可用于重建该对象的字符串表示。如果很明显它是什么(例如int或float),那些字符串将被解释回那些类型:

> JSON.dump(1234)
=> "1234"
> JSON.dump(1234.456)
=> "1234.456"
> JSON.dump(1.2e22)
=> "1.2e+22"

自动重建:

> JSON.parse(JSON.dump(1234))
=> 1234
> JSON.parse(JSON.dump(1.2e22))
=> 1.2e+22

BigDecimal使用您正在看到的特定表示:

> tgt=BigDecimal('0.12345')
=> 0.12345e0
> tgt.inspect
=> "0.12345e0"

虽然这是浮点字符串的合法格式,但如果采用该格式,它不会自动触发JSON解码器重建BigDecimal或float对象:

> JSON.parse(JSON.dump(tgt))
=> "0.12345e0"

您可以在编码为JSON之前调用.to_f(并且可能会失去BigDecimal的额外精度):

> JSON.parse(JSON.dump(tgt.to_f))
=> 0.12345

获得自动浮动。

或者,知道什么是BigDecimal并在条目上重新编码:

> BigDecimal(JSON.parse(JSON.dump(tgt)))
=> 0.12345e0

或者,您可以使用BigDecimal的format options转换为字符串浮点表示(不会丢失BigDecimal内部表示):

> tgt.to_s('F')
=> "0.12345"

但是,再次,当加载为JSON时,你可能会失去从BigDecimal =&gt; BigDecimal.to_s(&#39; F&#39;)=&gt;浮点数的准确性,因为解码器会自动将该表示转换为正常浮动。