Разбор JSON без каких-либо преобразований в Ruby

Я пишу скрипт Ruby для переноса файлов JSON из одного формата в другой. При этом мне нужно сохранить точное содержимое и форматирование всех значений. Есть ли в Ruby библиотека JSON, которая будет анализировать файл без какой-либо проверки или преобразования значений, просто оставляя их в виде строк?

Библиотека JSON по умолчанию преобразует все числа в формат с плавающей запятой, часто теряя точность. OJ может выполнить синтаксический анализ BigDecimal, но затем выведет все числа в экспоненциальной записи. Ни то, ни другое не позволяет мне вообще пропустить преобразование.

Не могли бы вы привести пример того, как вы теряете точность, когда библиотека JSON по умолчанию преобразует числа в числа с плавающей запятой? Возможно, я ошибаюсь, но я думал, что вы теряете точность при выполнении арифметических операций с числами с плавающей точкой, а не при преобразовании строковых значений в число с плавающей запятой.

GProst 07.08.2024 00:02

@GProst Для этого есть билет на Github: github.com/flori/json/issues/219 Если вы проанализируете «222.95816040039063», а затем сбросите его, вы получите обратно «222.95816040039062» (обратите внимание на последнюю цифру).

Don Reba 07.08.2024 01:07

Вы можете вызвать JSON#load с помощью процедуры, которая приводит объекты, похожие на числа с плавающей запятой, к объектам BigDecimal или String, что должно сохранять вашу точность.

Todd A. Jacobs 07.08.2024 05:50
Как сделать HTTP-запрос в Javascript?
Как сделать HTTP-запрос в Javascript?
В JavaScript вы можете сделать HTTP-запрос, используя объект XMLHttpRequest или более новый API fetch. Вот пример для обоих методов:
0
3
73
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Если вас интересует только анализ десятичных чисел, есть опция 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 из пользовательского класса.

Stefan 07.08.2024 15:14

Это как раз то, что мне нужно. Спасибо!

Don Reba 08.08.2024 20:26

Другие вопросы по теме