Json Ruby输出数字到小数点后2位
我无法将ruby对象序列化为json,更确切地说是数字的格式。 我已经编写了一个rspec测试来更准确地说明我的问题Json Ruby输出数字到小数点后2位,json,ruby,number-formatting,Json,Ruby,Number Formatting,我无法将ruby对象序列化为json,更确切地说是数字的格式。 我已经编写了一个rspec测试来更准确地说明我的问题 expected = '{ "foo": 1.00, "bar": 4.50, "abc": 0.00, "xyz": 1.23 }' it 'serializes as expected' do my_hash = { "foo": 1, "bar": 4.5, "abc": 0, "xyz": 1.23} expect(my_to_json_method(my_ha
expected = '{ "foo": 1.00, "bar": 4.50, "abc": 0.00, "xyz": 1.23 }'
it 'serializes as expected' do
my_hash = { "foo": 1, "bar": 4.5, "abc": 0, "xyz": 1.23}
expect(my_to_json_method(my_hash)).to eq expected
end
这就是我遇到的问题。我可以使用sprintf,但是如何获得上面示例中所示的字符串输出?用户sprintf
sprintf('.2f',5.5)
只需在JSON中插入一个ERB模板。您可以使用,
sprintf
,并可以通过提及%。(number)f
获取所需的小数点
例如:对于两位小数,%.2f
这是一个真正的实现
2.2.2 :019 > test = { "foo": (sprintf "%.2f","1.11"), "bar": (sprintf "%.2f","4.55"), "abc": (sprintf "%.2f","0.2") }
=> {:foo=>"1.11", :bar=>"4.55", :abc=>"0.20"}
放置“{”首先,您不应该使用浮点数来表示货币值。因此,让我们使用更合适的类型:(还有Ruby gem)
有几个选项可以表示货币值。根据JSON规范,以下所有JSON字符串都是有效的,并且在解析时都需要特殊处理。您可以选择最合适的字符串
注意:我正在实现一个自定义的to_json
方法,使用Ruby的默认json库将BigDecimal
实例转换为json。这只是为了演示,您通常不应该修补核心(或stdlib)类
1.具有固定精度的数字
请注意,许多JSON库在默认情况下会将这些数字解析为浮点值
class BigDecimal
def to_json(*)
'%.2f' % self
end
end
puts my_hash.to_json
输出:
{“foo”:1.00,“bar”:4.50,“abc”:0.00,“xyz”:1.23}
2.数字作为字符串
这将适用于所有JSON库,但将数字存储为字符串在我看来并不太合适
class BigDecimal
def to_json(*)
'"%.2f"' % self
end
end
puts my_hash.to_json
输出:
{“foo”:“1.00”,“bar”:“4.50”,“abc”:“0.00”,“xyz”:“1.23”}
3.作为整数的数字
你不需要用分数来表示货币价值,只需要把美分作为整数来输出,这是我通常做的
class BigDecimal
def to_json(*)
(self * 100).to_i.to_s
end
end
puts my_hash.to_json
输出:
{“foo”:100,“bar”:450,“abc”:0,“xyz”:123}
请尝试这个,test={“foo”:(sprintf“%.2f”,“1.0”),“bar”:(sprintf“%.2f”,“4.50”),“abc”:(sprintf“%.2f”,“0”)}
这些值的输出是字符串。因此,格式是有效的,但我希望结果不在结果中引用字符串。@mcbain83是否尝试存储货币值?是的,这是正确的。我不确定此行为在json字符串中是否有那么重要。但我仍然想看看现在是否有可能。警告:Floatin顾名思义,g点数字没有固定的精度。如果您想要精确的值,这对金钱特别重要,请改用。不要在金钱计算中使用浮点数。浮点数是一个值的精确近似值,而不是一个值的精确表示。如果您使用JSON进行传输,我会我强烈建议使用一个足够小的单位,你永远不需要分数,例如,美分对美元。你如何输出相同的值而不是字符串而是数值?test={“foo”:(sprintf“%.2f”,“1.11”)。tof,“bar”:(sprintf”%.2f”,“4.55”)。tof,“abc”:(sprintf”%.2f”,“0.2”)。tof}
当你在“1.30”上使用.tof时结果格式的字符串返回到原来的版本1.3。看看我修改过的问题。我把它作为一个rspec测试来编写,以更准确地描述我所寻找的内容。随着每次编辑,这段代码变得越来越离谱。这与Ruby的目的正好相反:不要重复自己是一个驱动原则,而且这段代码重复得荒谬。humm erb可能会工作。模板会是什么样子?感觉可能会有点混乱,有一大堆条件。我会试着做一个,看看是否可以发布一个结果…谢谢!是的,我正在使用money gem。我想避免讨论“用什么类型来赚钱”的问题,因为我想把重点放在n格式问题。我想你已经回答了。。这是一个很好的答案,不过我最好建议预先设置自定义模块和/或使用改进,而不是对核心库进行修补。@mcbain83在这种情况下,我会使用{“foo”:{“cents”:100,“currency”:“USD”}
@mudasobwa,黄色便条;)@Stefan让我们假设我无法更改预期的输出。您还建议使用money gem吗?所有格式选项似乎都是输出字符串。
class BigDecimal
def to_json(*)
'"%.2f"' % self
end
end
puts my_hash.to_json
class BigDecimal
def to_json(*)
(self * 100).to_i.to_s
end
end
puts my_hash.to_json