Я пишу скрипт Ruby для переноса файлов JSON из одного формата в другой. При этом мне нужно сохранить точное содержимое и форматирование всех значений. Есть ли в Ruby библиотека JSON, которая будет анализировать файл без какой-либо проверки или преобразования значений, просто оставляя их в виде строк?
Библиотека JSON по умолчанию преобразует все числа в формат с плавающей запятой, часто теряя точность. OJ может выполнить синтаксический анализ BigDecimal, но затем выведет все числа в экспоненциальной записи. Ни то, ни другое не позволяет мне вообще пропустить преобразование.
@GProst Для этого есть билет на Github: github.com/flori/json/issues/219 Если вы проанализируете «222.95816040039063», а затем сбросите его, вы получите обратно «222.95816040039062» (обратите внимание на последнюю цифру).
Вы можете вызвать JSON#load с помощью процедуры, которая приводит объекты, похожие на числа с плавающей запятой, к объектам BigDecimal или String, что должно сохранять вашу точность.
Если вас интересует только анализ десятичных чисел, есть опция decimal_class. Вы можете использовать это, чтобы выбрать другой класс, например BigDecimal, или предоставить свой собственный синтаксический анализатор:
string = "{\"num\":222.95816040039063}"
JSON.parse(string)
=> {"num"=>222.95816040039062}
JSON.parse(string, decimal_class: BigDecimal)
=> {"num"=>0.22295816040039063e3}
class NoConversion
def initialize(raw)
@raw = raw
end
end
JSON.parse(string, decimal_class: NoConversion)
=> {"num"=>#<NoConversion:0x0000000110509a90 @raw = "222.95816040039063">}
И, как отметил @Stefan, вы можете определить метод to_json
для генерации JSON из пользовательского десятичного класса:
class NoConversion
def initialize(raw)
@raw = raw
end
def to_json(*)
@raw
end
end
hash = JSON.parse(string, decimal_class: NoConversion)
=> {"num"=>#<NoConversion:0x0000000110511fd8 @raw = "222.95816040039063">}
JSON.generate(hash)
=> "{\"num\":222.95816040039063}"
Вы можете добавить def to_json(*) = @raw
, чтобы генерировать JSON из пользовательского класса.
Это как раз то, что мне нужно. Спасибо!
Не могли бы вы привести пример того, как вы теряете точность, когда библиотека JSON по умолчанию преобразует числа в числа с плавающей запятой? Возможно, я ошибаюсь, но я думал, что вы теряете точность при выполнении арифметических операций с числами с плавающей точкой, а не при преобразовании строковых значений в число с плавающей запятой.