问题摘要:我正在尝试使用Oj gem将哈希序列化为JSON。看来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
中的建议使用this answer,但是在某些情况下,我有哈希数组;尽管我可以从技术上为该数组中的每个哈希调用该方法,但考虑到Oj旨在加快Json序列化的速度,我更愿意找到一种使用Oj本身进行此操作的方法。最终,我想知道Oj中是否有一个选项或设置将执行此during序列化。
当我在写问题时,我找到了答案。由于我在StackOverflow上找不到与此问题相关的其他答案(特别是关于Oj gem的问题),因此我将保留此职位,希望对我的情况有所帮助。
根据this previously discussed issue on GitHub,将选项mode
设置为:compat
确实会将符号转换为字符串。所以我的渲染线现在看起来像这样:
render json: Oj.dump(example_hash, mode: :compat)
根据Oj documentation for default_options
,default_options
模式定义如下:
...与其他系统兼容。它将序列化任何对象,但将检查对象是否实现to_hash()或to_json()方法。如果存在,则使用该方法来序列化对象。的to_hash()更灵活,并产生更一致的输出,因此它优先于to_json()方法。如果两者都不是to_json()或to_hash()方法存在,则Oj内部Object变量使用编码。
因此,如果我正确地解释了这一点,则该解决方案似乎有效,因为它最终使用了:compat
类的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
选项相当,并且比普通的'ol Oj
效率要高得多。
这是包含基准代码的to_json
。
使用generate方法将提供相同的输出。
gist