2017-07-31 20 views
2

BigDecimalフィールドを含むRubyハッシュをJSONに変換する必要があります。Ruby jsonライブラリからBigDecimalを科学記法に変換する

私は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" 
} 

私はオブジェクトを解析する際に、BigDecimalのフィールドは、科学的表記に変換されることはありません数の書式を指定することができます任意のJSON libにはありますか?

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

私はあなたの望ましい結果を与える必要がありますルビー2.4.1p111

+0

'a = BigDecimal( '0.12345')'と 'a.to_f'のようなことをするとどうなりますか? – Abhinay

+0

知っていますが、知りたいのはJSON.parse(a)= 0.12345 – wduan

+0

を更新する方法です私の答え – Abhinay

答えて

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のは、あなたが見ている特定の表現を使用しています。すなわち、フロート文字列の合法的な形式であるが、それは自動的にその形式の場合のBigDecimalやフロートオブジェクトを再構築するためにJSONデコーダをトリガしない

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

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

あなたは前をJSONにエンコード(および潜在的にBigDecimalの余分な精度を失う)する.to_fを呼び出すことができます。

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

自動フロートを取得するには。

あるいは、BigDecimalのエントリに再エンコードが何であるかを知っている:

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

それとも、あなたは(BigDecimalの内部表現を失うことなく)文字列フロート表現に変換するためにはBigDecimalのformat optionsを使用することができます。

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

しかし、デコーダが自動的にその表現を通常のfloatに変換するため、BigDecimal => BigDecimal.to_s( 'F')=> floatの精度がJSONとしてロードされると、精度が低下する可能性があります。

+0

ありがとう、ありがとう。私はJSON.parse関数に頼るのではなく、まずBigDecimalを変換しなければならないと思います。 – wduan

+0

通常の浮動小数点または通常の整数の非常に高い精度を考慮して、JSONを使用することができます。 BigDecimalを使用する特定の理由がない限り、その方法は簡単です。 – dawg

0
BigDecimal('0.12345').to_f 

を使用しています。

更新:

JSON.parse(BigDecimal('0.12345').to_s) # => 0.12345 

JSON.parse(BigDecimal('0.12345').to_s).to_s # => "0.12345" 
+0

ありがとうございます。 JSON.parseを呼び出す前に、BigDecimalを適切な形式に変換することが唯一の方法だと思います。 – wduan

関連する問題