十进制的Rails JSON序列化添加引号

我对具有许多十进制和整数属性的模型使用默认的JSON序列化。 一个示例结果是:

{ "user": { "id": 1234, "rating": "98.7" } }

请注意,在“评级”的值周围添加了引号。 这会导致我正在使用的反序列化库将它们错误地视为字符串(而不是小数)。 可以将Rails设置为不对所有小数使用引号吗?

编辑:

如果可以,那么我使用的是Rails 3.0.7和Ruby 1.9.2。

编辑:

终奌站:

rails g model user rating:decimal
rake db:migrate

安慰:

user = User.create(rating: 98.7)
user.to_json
Kevin Sylvestre asked 2020-06-30T03:45:04Z
4个解决方案
43 votes

将小数从语言A传递到语言B的唯一“安全”方法是使用字符串。 如果您的json包含"rating": 98.79999999999999,则JavaScript运行时可能会将其转换为98.79999999999998

请参阅BigDecimal as_json文档:

一个自然的BigDecimal 表示为JSON编号。 最 库,但是,解析非整数 JSON数字直接作为浮点数。 使用这些库的客户会 通常得到一个错误的数字,没有 除了手动恢复的方法 使用JSON检查字符串 代码本身。

这就是为什么要返回JSON字符串的原因。 JSON文字不是数字,而是 如果对方知道合同规定 该数据应该是 BigDecimal,它仍然有机会 后处理字符串并获取 实际价值。

如果要强制Rails不要引用这些,则可以猴子补丁BigDecimal(请参见Rails源代码)。

# 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
Marcel Jackwerth answered 2020-06-30T03:45:37Z
28 votes

对于Rails 4.0,此选项已更改,它具有选项ActiveSupport.encode_big_decimal_as_string,因此您可以指定BigDecimal序列化首选项。 见问题6033

同时,如果您对6033年提出的参数感到满意,并且正在运行低于4.0的Rails版本,则可以按以下方式猴子对BigDecimal进行补丁

require 'bigdecimal'

class BigDecimal
  def as_json(options = nil) #:nodoc:
    if finite?
      self
    else
      NilClass::AS_JSON
    end
  end
end

这解决了RABL为存储为BigDecimal的美元金额抽出字符串的问题。

toxaq answered 2020-06-30T03:46:06Z
10 votes

如果使用ActiveModel :: Serializer,则还可以使用to_f强制从Decimal转换为Float类型。 这也将为您节省报价!

所以在您的对象序列化器类中。 做

def rating
  self.rating.to_f
end
alexzg answered 2020-06-30T03:46:31Z
0 votes

使用Rails 5时,encode_big_decimal_as_string不起作用(已弃用,因此在此不会感到惊讶)。

如果将jbuilder添加到您的应用程序

# Gemfile
gem 'jbuilder', '~> 2.5'

然后只需创建一个json视图,将十进制转换为仅用于该视图的float,就应该是黄金的。

# app/views/yourmodel/index.json.jbuilder
json.array! @yourmodels do |yourmodel|
  json.attributethatisadecimal yourmodel.attributethatisadecimal.to_f
end

这对我来说效果很好-要做更多的工作(因为您必须将模型映射到jbuilder),但是这种方法看起来很干净。

jfgrissom answered 2020-06-30T03:47:04Z
translate from https://stackoverflow.com:/questions/6128794/rails-json-serialization-of-decimal-adds-quotes