我需要将包含一些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
答案 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;浮点数的准确性,因为解码器会自动将该表示转换为正常浮动。