Резюме проблемы: я пытаюсь сериализовать хэш в JSON с помощью гемма Oj . Похоже, что Oj не преобразует автоматически символьные ключи хэша в строки. Мне интересно, есть ли у Oj возможность "строкового преобразования" во время сериализации?

Это пример моего хеша:

example_hash = 
 {:id=>1234,
  :asset_number=>"1234-5678",
  :latitude=>34.78495,
  :longitude=>-92.12899,
  :last_tracking_record_id=>123456789,
  :bearing=>42,
  :threat_level=>:severe}

И это выглядит так:

render json: Oj.dump(example_hash)

К сожалению, полученный JSON имеет ключи, которые выглядят точно так же, как указано выше, а это означает, что мне нужно будет получить доступ к элементам в JavaScript следующим образом: response[:asset_number]. Поскольку код на стороне клиента был реализован несколько месяцев назад и только сейчас добавлен Oj, я бы предпочел найти способ привязать ключи во время сериализации на стороне сервера.

У Oj есть опция symbol_keys, которая является логической, однако установка для нее значения true или false в этом отношении не имеет никакого эффекта.

Единственное решение, которое я нашел до сих пор, - использовать with_indifferent_access, как предлагается в этом ответе, однако в некоторых случаях У меня есть массивы хешей; хотя я могу технически вызывать этот метод для каждого хэша в этом массиве, учитывая, что Oj предназначен для ускорения сериализации Json, я бы предпочел найти способ сделать это с самим Oj. В конце концов, мне интересно, есть ли в Oj параметр или параметр, который будет выполнять эту во время сериализации.

9
Paul Richter 9 Янв 2014 в 23:17

2 ответа

Лучший ответ

Пока я писал вопрос, я смог найти ответ. Поскольку я не могу найти других ответов на StackOverflow по этой проблеме (особенно в отношении драгоценного камня Oj), я сохраню этот пост в надежде, что он поможет другим в моей ситуации.

Согласно этой ранее обсуждавшейся проблеме на GitHub, установив для параметра mode значение :compat действительно преобразует символы в строки. Итак, моя линия рендеринга теперь выглядит так:

render json: Oj.dump(example_hash, mode: :compat)

Согласно документации Oj для default_options, :compat режим определяется следующим образом:

... совместим с другими системами. Он будет сериализовать любой объект, но проверит, реализует ли объект метод to_hash () или to_json (). Если какой-либо из них существует, этот метод используется для сериализации объекта. To_hash () более гибкий и дает более согласованный вывод, поэтому он имеет преимущество перед методом to_json (). Если методы to_json () или to_hash () отсутствуют, то используется кодировка внутренней переменной объекта Oj.

Итак, если я интерпретирую это правильно, похоже, что это решение работает, потому что в конечном итоге оно использует метод to_json класса Hash.

Я не уверен, повлиял ли я на производительность (положительно или отрицательно), но, по крайней мере, это избавляет меня от необходимости вручную вызывать with_indifferent_access или to_json в случае массива.

Обновить

Что касается производительности, cmwright провел некоторое тестирование производительности и получил следующие результаты:

Rehearsal ----------------------------------------------
json        13.990000   0.250000  14.240000 ( 14.257051)
oj default   3.260000   0.230000   3.490000 (  3.491028)
oj compat    3.360000   0.240000   3.600000 (  3.593109)
------------------------------------ total: 21.330000sec

                 user     system      total        real
json        13.740000   0.240000  13.980000 ( 13.992641)
oj default   3.020000   0.230000   3.250000 (  3.248077)
oj compat    3.060000   0.230000   3.290000 (  3.286443)

Похоже, что параметр compat, по крайней мере, соответствует параметрам по умолчанию Oj и значительно более эффективен, чем простой 'ol to_json.

Это суть, содержащая тестовый код.

13
Community 23 Май 2017 в 12:26

Использование метода генерации дает тот же результат.

Oj.generate({a: `test`}) 
1
DenniJensen 10 Янв 2020 в 14:42