问题描述
对于具有多个小数和整数属性的模型,我正在使用默认的 JSON 序列化.一个示例结果是:
I'm using the default JSON serialization for a model that has a number of decimal and integer attributes. An example result is:
{ "user": { "id": 1234, "rating": "98.7" } }
请注意在评级"值周围添加了引号.这导致我使用的反序列化库错误地将它们视为字符串(而不是小数).可以将 Rails 设置为不对所有小数使用引号吗?
Notice the addition of quotes around the value of "rating". This causes the deserialization library I'm using to incorrectly treat these as strings (instead of decimals). Can Rails be set to not use the quotes for all decimals?
如果有所不同,我使用的是 Rails 3.0.7 和 Ruby 1.9.2.
I'm on Rails 3.0.7 and Ruby 1.9.2 if that makes a difference.
终端:
rails g model user rating:decimal
rake db:migrate
控制台:
user = User.create(rating: 98.7)
user.to_json
推荐答案
将小数从语言 A 传递到语言 B 的唯一安全"方法是使用字符串.如果您的 json 包含 "rating": 98.79999999999999
它可能会被您的 JavaScript 运行时转换为 98.79999999999998
.
The only "safe" way to hand decimals from language A to language B is to use a String. If your json contains "rating": 98.79999999999999
it will probably be converted to 98.79999999999998
by your JavaScript runtime.
请参阅 BigDecimal as_json 文档:
一个 BigDecimal 自然是表示为 JSON 数字.最多然而,库解析非整数JSON 数字直接作为浮点数.使用这些库的客户会一般得到一个错误的数字,没有手动恢复以外的方法使用 JSON 检查字符串代码本身.
这就是返回 JSON 字符串的原因.JSON 文字不是数字,而是如果另一端通过合同知道数据应该是一个BigDecimal,它还有机会对字符串进行后处理并得到真正的价值.
That’s why a JSON string is returned. The JSON literal is not numeric, but if the other end knows by contract that the data is supposed to be a BigDecimal, it still has the chance to post-process the string and get the real value.
如果你想强制 Rails 不引用这些,你可以猴子补丁 BigDecimal(参见 Rails 源).
If you want to force Rails not to quote these, you could monkey-patch BigDecimal (see Rails source).
# not needed: to compare with the Numeric implementation
class Numeric
def as_json(options = nil) self end #:nodoc:
def encode_json(encoder) to_s end #:nodoc:
end
class BigDecimal
def as_json(options = nil) self end
def encode_json(encoder) to_s end #:nodoc:
end
这篇关于十进制的 Rails JSON 序列化添加引号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!