Подтвердить что ты не робот

Rails JSON Сериализация десятичных добавлений Цитаты

Я использую сериализацию JSON по умолчанию для модели с числом десятичных и целочисленных атрибутов. Пример:

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

Обратите внимание на добавление котировок вокруг значения "рейтинг". Это приводит к тому, что библиотека десериализации я использую, чтобы неправильно рассматривать их как строки (вместо десятичных знаков). Может ли Rails установить, чтобы не использовать кавычки для всех десятичных знаков?

Edit:

Я на Rails 3.0.7 и Ruby 1.9.2, если это имеет значение.

Edit:

Терминал:

rails g model user rating:decimal
rake db:migrate

Консоль:

user = User.create(rating: 98.7)
user.to_json
4b9b3361

Ответ 1

Это изменилось для Rails 4.0, у которого есть опция ActiveSupport.encode_big_decimal_as_string, чтобы вы могли указать предпочтение сериализации BigDecimal. См. вопрос 6033

Тем временем, если вам нравится аргумент, поставленный в 6033 году, и вы используете версию Rails ниже 4.0, вы можете обезглавить BigDecimal, как показано ниже

require 'bigdecimal'

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

Это решило мои проблемы с RABL, выкачивая строки для сумм в долларах, хранящихся как BigDecimal.

Ответ 2

Единственным "безопасным" способом передачи десятичных знаков с языка A на язык B является использование String. Если ваш json содержит "rating": 98.79999999999999, он, вероятно, будет преобразован в 98.79999999999998 по вашей среде выполнения JavaScript.

Смотрите документацию 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

Ответ 3

если вы используете ActiveModel:: Serializer, вы также можете использовать to_f для принудительного преобразования из десятичного в тип Float. что вы также украдете цитату для вас!

поэтому в классе объектов сериализатора. do

def rating
  self.rating.to_f
end

Ответ 4

С 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), но этот подход кажется довольно чистым.